Python奇幻之旅(从入门到入狱高级篇)——面相对象进阶【中】

目录

2. 面向对象进阶

2.1. 成员

2.2. 变量

2.2. 方法

2.4. property属性

2.5. 成员修饰符

2.6. 对象嵌套

2.7. 特殊成员


引言

本篇内容主要是面向对象的进阶,讲解一些特殊的成员和方法,更加深入迭代器是如何通过对象实现的。

2. 面向对象进阶

2.1. 成员

面向对象中的所有成员如下:

  • 变量
    • 实例变量
    • 类变量
  • 方法
    • 绑定方法
    • 类方法
    • 静态方法
  • 属性

通过面向对象进行编程时,会遇到很多种情况,也会使用不同的成员来实现,接下来我们来逐一介绍成员特性和应用场景。

2.2. 变量

  • 实例变量,属于对象,每个对象中各自维护自己的数据。
  • 类变量,属于类,可以被所有对象共享,一般用于给对象提供公共数据(类似于全局变量)。

class Person(object):country = "中国"def __init__(self, name, age):self.name = nameself.age = agedef show(self):# message = "{}-{}-{}".format(Person.country, self.name, self.age)message = "{}-{}-{}".format(self.country, self.name, self.age)print(message)print(Person.country) # 中国p1 = Person("jiaoxingk",20)
print(p1.name)
print(p1.age)
print(p1.country) # 中国p1.show() # 中国-jiaoxingk-20

提示:当把每个对象中都存在的相同的示例变量时,可以选择把它放在类变量中,这样就可以避免对象中维护多个相同数据。

2.2. 方法

  • 绑定方法,默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象&类均可调用】
  • 类方法,默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象&类均可调用】
  • 静态方法,无默认参数,用类和对象都可以调用。【对象&类均可调用】

class Foo(object):def __init__(self, name,age):self.name = nameself.age = agedef f1(self):print("绑定方法", self.name)@classmethoddef f2(cls):print("类方法", cls)@staticmethoddef f3():print("静态方法")# 绑定方法(对象)
obj = Foo("jiaoxingk",20)
obj.f1() # Foo.f1(obj)# 类方法
Foo.f2()  # cls就是当前调用这个方法的类。(类)
obj.f2()  # cls就是当前调用这个方法的对象的类。# 静态方法
Foo.f3()  # 类执行执行方法(类)
obj.f3()  # 对象执行执行方法

在Python中比较灵活,方法都可以通过对象和类进行调用;而在java、c#等语言中,绑定方法只能由对象调用;类方法或静态方法只能由类调用。

在类中 @classmethod 和 @staticmethod 的区别?

1 . @staticmethod不需要表示自身对象的self和自身类的cls参数(这两个参数都不需要添加),就跟使用函数一样。


2 . @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。

class A:@classmethoddef test(cls):     #必须有cls参数, 表示调用当前的类名print("hello")T.test()
T().test()

2.4. property属性

其实就是可以让调用属性一样去调用方法,也就是不需要加上()

属性其实是由绑定方法 + 特殊装饰器 组合创造出来的,让我们以后在调用方法时可以不加括号,例如:

class Foo(object):def __init__(self, name):self.name = namedef f1(self):return 123@propertydef f2(self):return 123obj = Foo("jiaoxingk")v1 = obj.f1()
print(v1)v2 = obj.f2
print(v2)

关于属性的编写有两种方式:

  • 方式一,基于装饰器
class C(object):@propertydef x(self):pass@x.setterdef x(self, value):pass@x.deleterdef x(self):passobj = C()obj.x
obj.x = 123
del obj.x

  • 方式二,基于定义变量
class C(object):def getx(self): passdef setx(self, value): passdef delx(self): passx = property(getx, setx, delx, "I'm the 'x' property.")obj = C()obj.x
obj.x = 123
del obj.x

写在最后,对property属性进行一个补充:

由于property属性和实例变量的调用方式相同,所以在编写时需要注意:属性名称 不要 实例变量 重名。

class Foo(object):def __init__(self, name, age):self.name = nameself.age = age@propertydef func(self):return 123obj = Foo("jiaoxingk", 123)
print(obj.name)
print(obj.func)

一旦重名,可能就会有报错。

class Foo(object):def __init__(self, name, age):self.name = name  # 报错,错认为你想要调用 @name.setter 装饰的方法。self.age = age@propertydef name(self):return "{}-{}".format(self.name, self.age)obj = Foo("jiaoxingk", 123)

如果真的想要在名称上创建一些关系,可以让实例变量加上一个下划线。

class Foo(object):def __init__(self, name, age):self._name = nameself.age = age@propertydef name(self):return "{}-{}".format(self._name, self.age)obj = Foo("jiaoxingk", 123)
print(obj._name)
print(obj.name)

2.5. 成员修饰符

Python中成员的修饰符就是指的是:公有、私有。

  • 公有,在任何地方都可以调用这个成员。
  • 私有,只有在类的内部才可以调用改成员(成员是以两个下划线开头,则表示该成员为私有)。

示例一:

class Foo(object):def __init__(self, name, age):self.__name = nameself.age = agedef get_data(self):return self.__namedef get_age(self):return self.ageobj = Foo("jiaoxingk", 123)# 公有成员
print(obj.age)
v1 = self.get_age()
print(v1)# 私有成员
# print(obj.__name) # 错误,由于是私有成员,只能在类中进行使用。
v2 = obj.get_data()
print(v2)

示例2:

class Foo(object):def get_age(self):print("公有的get_age")def __get_data(self):print("私有的__get_data方法")def proxy(self):print("公有的proxy")self.__get_data()obj = Foo()
obj.get_age()obj.proxy()

特别提醒:父类中的私有成员,子类无法继承。

class Base(object):def __data(self):print("base.__data")def num(self):print("base.num")class Foo(Base):def func(self):self.num()self.__data() # # 不允许执行父类中的私有方法obj = Foo()
obj.func()

写在最后,按理说私有成员是无法被外部调用,但如果用一些特殊的语法也可以(一般不建议)。

class Foo(object):def __init__(self):self.__num = 123self.age = 19def __msg(self):print(1234)obj = Foo()
print(obj.age)
print(obj._Foo__num)
obj._Foo__msg()

成员是否可以作为独立的功能暴露给外部,让外部调用并使用。

  • 可以,公有。
  • 不可以,内部其他放的一个辅助,私有。

2.6. 对象嵌套

在基于面向对象进行编程时,对象之间可以存在各种各样的关系,例如:组合、关联、依赖等(Java中的称呼),通俗来说就是各种嵌套。

class Student(object):""" 学生类 """def __init__(self, name, age):self.name = nameself.age = agedef message(self):data = "我是一名学生,我叫:{},我今年{}岁".format(self.name, self.age)print(data)s1 = Student("jiaoxingk", 19)
s2 = Student("jiaoxingk", 19)
s3 = Student("日天", 19)class Classes(object):""" 班级类 """def __init__(self, title):self.title = titleself.student_list = []def add_student(self, stu_object):self.student_list.append(stu_object)def add_students(self, stu_object_list):for stu in stu_object_list:self.add_student(stu)def show_members(self):for item in self.student_list:# print(item)item.message()c1 = Classes("五年三班")
c1.add_student(s1)
c1.add_students([s2, s3])print(c1.title)
print(c1.student_list)

可以看到,我们定义了一个班级类和学生类,我们通过班级来创建一个学生列表,其中的对象都是Student对象,相当于把Student对象嵌套进了Classes对象里面

2.7. 特殊成员

在Python的类中存在一些特殊的方法,这些方法都是 __方法__ 格式,这种方法在内部均有特殊的含义,接下来我们来看一些常见的特殊成员:

  •  __new__,构造方法

创建空对象 , 相当于申请一个空间来建房子

class Foo(object):def __init__(self, name):print("第二步:初始化对象,在空对象中创建数据")self.name = namedef __new__(cls, *args, **kwargs):print("第一步:先创建空对象并返回")return object.__new__(cls)obj = Foo("jiaoxingk")

  • __init__,初始化方法

用于进行初始化属性的 , 相当于开始装修

class Foo(object):def __init__(self, name):self.name = nameobj = Foo("jiaoxingk")

  • __call__

当一个类实现了__call__方法时,你可以像调用函数一样调用该类的实例

class CallableClass:def __init__(self, name):self.name = namedef __call__(self, x):print(f"{self.name} called with argument {x}")# 创建一个CallableClass的实例
obj = CallableClass("MyCallable")# 调用实例,触发__call__方法
obj(42)

  • __str__

当你使用str()函数或print()函数来获取对象的字符串表示时,Python会调用对象的__str__方法

class MyClass:def __init__(self, value):self.value = valuedef __str__(self):return f"MyClass instance with value: {self.value}"# 创建一个MyClass的实例
obj = MyClass(42)# 使用str()函数获取对象的字符串表示
str_representation = str(obj)# 使用print()函数打印对象的字符串表示
print(obj)

  • __dict__

将属性生成字典

class Foo(object):def __init__(self, name, age):self.name = nameself.age = ageobj = Foo("jiaoxingk",19)
print(obj.__dict__)# {'name': 'jiaoxingk', 'age': 19}

  • __getitem____setitem____delitem__

是Python中用于实现可索引(indexable)和可切片(slicable)对象的特殊方法。它们分别用于访问、设置和删除对象的元素,使得对象可以像列表或字典一样被操作。

class MyList:def __init__(self):self.items = []def __getitem__(self, index):return self.items[index]def __setitem__(self, index, value):self.items[index] = valuedef __delitem__(self, index):del self.items[index]def __len__(self):return len(self.items)# 创建一个MyList的实例
my_list = MyList()# 使用__setitem__添加元素
my_list[0] = 1
my_list[1] = 2
my_list[2] = 3# 使用__getitem__获取元素
print(my_list[1])  # 输出: 2# 使用__delitem__删除元素
del my_list[1]# 查看修改后的列表
print(my_list.__dict__)  # 输出: {'items': [1, 3]}

  • __enter____exit__

用于实现Python上下文管理器(Context Managers)的两个特殊方法

上下文管理器用于在代码块执行前后执行一些操作,例如资源的获取和释放,文件的打开和关闭等

class Foo(object):def __enter__(self):print("进入了")return 666def __exit__(self, exc_type, exc_val, exc_tb):print("出去了")obj = Foo()
with obj as data:print(data)

  • __add__

用于定义对象之间的加法操作

class Foo(object):def __init__(self, name):self.name = namedef __add__(self, other):return "{}-{}".format(self.name, other.name)v1 = Foo("jiaoxingk")
v2 = Foo("sb")# 对象+值,内部会去执行 对象.__add__方法,并将+后面的值当做参数传递过去。
v3 = v1 + v2
print(v3)

  • __iter__
    • 迭代器
# 迭代器类型的定义:1.当类中定义了 __iter__ 和 __next__ 两个方法。2.__iter__ 方法需要返回对象本身,即:self3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types# 创建 迭代器类型 :class IT(object):def __init__(self):self.counter = 0def __iter__(self):return selfdef __next__(self):self.counter += 1if self.counter == 3:raise StopIteration()return self.counter# 根据类实例化创建一个迭代器对象:obj1 = IT()# v1 = obj1.__next__()# v2 = obj1.__next__()# v3 = obj1.__next__() # 抛出异常v1 = next(obj1) # obj1.__next__()print(v1)v2 = next(obj1)print(v2)v3 = next(obj1)print(v3)obj2 = IT()for item in obj2:  # 首先会执行迭代器对象的__iter__方法并获取返回值,一直去反复的执行 next(对象) print(item)迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。
for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。

    • 生成器
# 创建生成器函数def func():yield 1yield 2# 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__ 方法。obj1 = func()v1 = next(obj1)print(v1)v2 = next(obj1)print(v2)v3 = next(obj1)print(v3)obj2 = func()for item in obj2:print(item)如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(生成器也是一个中特殊的迭代器)。

    • 可迭代对象
# 如果一个类中有__iter__方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。class Foo(object):def __iter__(self):return 迭代器对象(生成器对象)obj = Foo() # obj是 可迭代对象。# 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:pass

class IT(object):def __init__(self):self.counter = 0def __iter__(self):return selfdef __next__(self):self.counter += 1if self.counter == 3:raise StopIteration()return self.counterclass Foo(object):def __iter__(self):return IT()obj = Foo() # 可迭代对象for item in obj: # 循环可迭代对象时,内部先执行obj.__iter__并获取迭代器对象;不断地执行迭代器对象的next方法。print(item)

class Foo(object):def __iter__(self):yield 1yield 2obj = Foo()
for item in obj:print(item)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/697111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bellman-Ford(贝尔曼福特算法)

简介 贝尔曼-福特算法(Bellman-Ford Algorithm)是一种用于求解单源最短路径问题的算法,它可以处理带有负权边的图。 该算法的实现思路是通过不断迭代松弛操作来更新最短路径,直到找到最优解。 名词解释:1. 松弛操作&…

Qt 获取控件尺寸与实际不一致的问题

前提:界面ui获取桌面大小,用resize() 重新调整了界面尺寸 然后 我获取界面上某个控件大小时,发现与实际尺寸不一样。 最后发现: 获取控件大小的地方,必须在界面show()之后才可以,放之前不行。 注意; 经…

WPF 控件禁用时,显示悬浮提示

WPF 控件禁用时&#xff0c;显示悬浮提示 控件在禁用状态下&#xff0c;按钮是没有悬浮提示信息的&#xff0c;是事件触发的机制&#xff1b; 如果要禁用下也有悬浮提示&#xff0c;可以在控件外面加一层&#xff0c;例如&#xff1a; <Border Grid.Column"1" To…

Hive【内部表、外部表、临时表、分区表、分桶表】【总结】

目录 Hive的物种表结构特性 一、内部表 建表 使用场景 二、外部表 建表:关键词【EXTERNAL】 场景&#xff1a; 外部表与内部表可互相转换 三、临时表 建表 临时表横向对比​编辑 四、分区表 建表&#xff1a;关键字【PARTITIONED BY】 场景&#xff1a; 五、分桶表 …

CentOS 7.x 使用 RPM 包安装 Gitlab

官网&#xff1a;https://about.gitlab.com/ https://about.gitlab.cn/install/ 安装&#xff1a;https://gitlab.cn/install/ 博客&#xff1a;https://gitlab.cn/blog/ 文档&#xff1a;https://docs.gitlab.com/ https://about.gitlab.com/install/#centos-7 https://docs.g…

工作记录vue3 echarts地图等 监听浏览器等写法

子组件<template><div><div>【云端报警风险】</div><div ref"target" class"w-full h-full"></div></div> </template><script setup> import { ref, onMounted,watch } from vue; import * as ech…

算能RISC-V通用云开发空间编译pytorch @openKylin留档

终于可以体验下risc-v了&#xff01; 操作系统是openKylin&#xff0c;算能的云空间 尝试编译安装pytorch 首先安装git apt install git 然后下载pytorch和算能cpu的库&#xff1a; git clone https://github.com/sophgo/cpuinfo.git git clone https://github.com/pytorc…

小米14 Ultra:未来科技的集大成者

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

opencv图像的本质

目的 OpenCV是一个跨平台的库&#xff0c;使用它我们可以开发实时的计算机视觉应用程序。 它主要集中在图像处理&#xff0c;视频采集和分析&#xff0c;包括人脸检测和物体检测等功能。 数字图像在计算机中是以矩阵形式存储的&#xff0c;矩阵中的每一个元素都描述一定的图像…

VSCode React JavaScript Snippets 插件的安装与使用指南

VSCode React JavaScript Snippets 插件的安装与使用指南 在开发 React 项目时&#xff0c;提高效率是每个开发者都追求的目标之一。VSCode React JavaScript Snippets 插件就是为了提升 React 开发效率而设计的&#xff0c;它为常用的 React 代码片段提供了快捷键&#xff0c;…

NXP实战笔记(六):S32K3xx基于RTD-SDK在S32DS上配置PWM发波

目录 1、概述 2、SDK配置 2.1、Port配置 2.2、Emios_Mcl_Ip 2.3、Emios_Pwm 2.4、代码示例 1、概述 针对S32K3xx芯片&#xff0c;产生PWM的硬件支持单元仅有两个&#xff0c;分别是eMiosx与Flexio. 生成PWM的顺序&#xff0c;按照单片机所用资源进行初始化执行如下 初始化…

去年面试的运维开发面试题二

VPN有哪些协议&#xff0c;不同协议之间有何区别&#xff1f; 2.内部组网通常使用哪些类型的网段&#xff0c;两个不同网段如何通信&#xff1f; 3.Linux中绝对路径&#xff0c;相对路径的区别 4. Linux如何添加磁盘&#xff0c;扩容系统文件&#xff1f; 5. Linux如何查看进程…

原型模式(Prototype Pattern) C++

上一节&#xff1a;建造者模式&#xff08;Builder Pattern&#xff09;C 文章目录 0.理论1.原型模式的核心组成&#xff1a;2.实现方法3.什么时候使用 1.实践步骤 1: 定义怪物原型步骤 2: 实现具体怪物原型步骤 3: 使用原型创建怪物 0.理论 原型模式&#xff08;Prototype P…

7-liunx服务器规范

目录 概况liunx日志liunx系统日志syslog函数openlog 可以改变syslog默认输出方式 &#xff0c;进一步结构化 用户信息进程间的关系会话ps命令查看进程关系 系统资源限制改变工作目录和根目录服务器程序后台话 概况 liunx服务器上有很多细节需要注意 &#xff0c;这些细节很重要…

服务网格Service Mesh和Istio

文章目录 服务网格&#xff08;Service Mesh&#xff09;市场上三种服务网格解决方案服务网格的特征流量管理安全性可观察性 Istio简介Istio提供了什么功能服务 &#xff1f;Istio 核心特性流量管理安全可观察性 平台支持 服务网格&#xff08;Service Mesh&#xff09; 服务网…

Eureka注册中心(黑马学习笔记)

Eureka注册中心 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 大家思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f; 有多个user-service实例地址&#xff0c…

六、行列式基本知识

目录 1、行列式的特性 2、行列式的计算方法: 2.1 通过行列式的定义去计算:对角法则。 2. 2 利用行列式的性质将行列式转化为上三角行列式: ①行列式的性质 : 性质一: 性质二: 性质三: 性质四:行列式之间的加法

TreeData 数据查找

TreeData 数据查找 最近做需求的时候遇到了这样的一个需求&#xff0c;Tree组件数据支持查找&#xff0c;而且TreeData的数据层级是无限级的 开始想的事借助UI组件库&#xff08;Ant-design-vue&#xff09;中的Tree组件的相关方法直接实现,看了下api 发现没法实现&#xff0c;…

超级实用的python代码片段汇总和详细解析(16个)

目录 1. 生成随机文本 2. 计算文本文件中的字数 3. 替换文件文件中的字串 4. 多文件名的批量替换 5. 从网站提取数据 6. 批量下载图片 7.批量删除空文件夹 8.Excel表格读写 9.合并Excel表格工作簿 10.数据库SQL查询 11. 系统进程查杀 12.图像尺寸调整和裁剪 13.图…

redis实现消息队列redis发布订阅redis监听key

文章目录 Redis消息队列实现异步秒杀1. jvm阻塞队列问题2. 什么是消息队列3. Redis实现消息队列1. 基于List结构模拟消息队列操作优缺点 2. 基于PubSub发布订阅的消息队列操作优缺点spring 结合redis的pubsub使用示例1. 引入依赖2. 配置文件3. RedisConfig4. CustomizeMessageL…