python面向对象编程(三)
- 成员修饰符
共有成员; 外部对象可以直接访问
私有成员; 变量前加2下划线,默认为创建的为私有成员。无法直接访问,只能通过创建中间函数间接访问。
class foo:
sex1 = 'men1'
__sex = 'men'
def __init__(self,name,age):
self.name = name
self.__age = age
def show(self):
return self.__age
@staticmethod
def show2()
return foo.__sex
obj = foo('gao','18')
print(obj.name) # gao
print(obj.__age) # 报错 AttributeError: 'foo' object has no attribute 'age'
print(obj.show()) # 18 可以已此方法访问
print(foo.sex1) # men1 静态字段同样支持此方式
print(foo.__sex1) # 报错 AttributeError: 'foo' object has no attribute '__sex1'
print(foo.show2()) # men
上代码看到,无论普通字段还是静态字段,均具有共有私有方法;
那么看看方法有没有共私有之分
class foo:
def __fi(self):
return 123
def f2(self):
r = self.__fi()
return r
f = foo()
print(f.f2()) # 123
方法,同样有共有私有之分,当然属性也存在共私有之分,但基本上不会使用。
只有在字段与方法上,会使用成员修饰符进行共私有设置。
注意:私有不支持继承,只能自己另外创建一个共有方法间接访问父类私有
-
特殊成员
__init__:先前说的一个__init__构造方法就是一个特殊成员:当类加括号是,默认执行__init__
__new__:new方法与init几乎一致,都是在创建对象时自动执行的。两者的区别是:
a 、__new__方法是创建对象时执行的;__init__方法是初始化对象时执行的;
b 、__new__方法传入第一个参数是cls即类本身,作用是将类对象本身作为模板去创建一个实列对象;__init__方法传入第一个参数是self,即已经实列的对象;
c 、__new__方法必须要有返回值,返回值就是新建的对象;__init__方法没有返回值;
使用__new__方法构建单例模式:class foo: _instance = None def __new__(cls): if cls._instance is None: cls._instance = object.__new__(cls) return cls._instance a = foo() b = foo() print(id(a),a) # 2192770708368 <__main__.foo object at 0x000001FE8B51B390> print(id(b),b) # 2192770708368 <__main__.foo object at 0x000001FE8B51B390> # 根据id可以看出,a、b这两个id时完全一致的,故这两个实 例实际上是一个__del__析构方法:构造方法时创建对象时执行的,析构方法是,对象销毁时,自动执行的,一般用不到,是python垃圾回收机构销毁对象时,自动处理了,我们无法管控。
__call__:当类创建对象时,可以在对象后加括号,默认为执行__call__这个特殊方法class foo: def __init__(self): print('init') def __call__(self): print('call') a = foo() # init a() # call__int__、__str__:这俩种方式在对象调用int()或str()函数时,会自动调用此两种方法:class foo: def __init__(self,name): self.name = name def __int__(self): return 111 def __str__(self): return self.name a = foo('gao') # init print(a) # gao 当类中没有定义__str__特殊成员时 打印的内容为 <__main__.foo object at 0x000002887294B2E8> print(str(a)) # gao print(int(a)) # 111__add__:两对象相加时,自动执行第一个对象的__add__方法,并将第二个对象当参数传入。执行逻辑自定义class foo: def __init__(self,n,a): self.name = n self.age = a def __add__(self, other): return self.age+other.age obj1 = foo('gao',21) obj2 = foo('qi',20) a = obj1+obj2 print(a) # 41除了
__add__加方法,还有减乘除,不多展示;__dict__:将对象中封装的所有内容通过字典的形式返回,或将类中的成员已字典形式返回class foo: ''' 注释: foo 是用来测试__dict__方法返回类成员的 ''' def __init__(self,n,a): self.name = n self.age = a obj1 = foo('gao',21) obj2 = foo('qi',20) a = obj1.__dict__ print(a) # {'name': 'gao', 'age': 21} print(foo.__dict__) # {'__module__': '__main__', '__doc__': '\n \t\t注释:\n \t\tfoo 是用来测试__dict__方法返回类成员的\n ', '__init__': <function foo.__init__ at 0x00000133A6A800D0>, '__dict__': <attribute '__dict__' of 'foo' objects>, '__weakref__': <attribute '__weakref__' of 'foo' objects>}__getitem__、__setitem__、__delitem__:基于列表的方式,处理对象。class foo: def __init__(self, n, a): self.name = n self.age = a def __getitem__(self, item): return item + 10 def __setitem__(self, key, value): print('__setitem__',key, value) def __delitem__(self, key): print('__delitem__',key) obj1 = foo('gao', 21) a = obj1[10] print(a) # 20 obj1[2] = 'aa' # __setitem__ 2 aa del obj1[12] # __delitem__ 12在学列表对于列表处理时:除了增删改查,还有个切片处理:
class foo: def __init__(self, n, a): self.name = n self.age = a def __getitem__(self, item): print(item,type(item)) return item,type(item) obj1 = foo('gao', 21) obj1[10] # 10 <class 'int'> obj1[1:10:2] # slice(1, 10, 2) <class 'slice'>可以看出,在做切片时,传入的是一个名为
slice的对象,那么,在处理切片时,即可以如下处理;class foo: def __init__(self, n, a): self.name = n self.age = a def __getitem__(self, item): print(item,type(item)) if type(item) == slice: print('调用切片处理') print(item.start) # 切片开始位置 print(item.stop) # 切片结束位置 print(item.step) # 切片步长 ''' 添加自己想要添加的处理方式即可 ''' else: print('调用内部索引处理') return item,type(item) obj1 = foo('gao', 21) obj1[10] # 10 <class 'int'> 调用内部索引处理 obj1[1:10:2] # slice(1, 10, 2) <class 'slice'> 调用切片处理 1 10 2__iter__:之前学习迭代器时,有个iter()方法,可以将一个可迭代对象生成一个迭代器,现在一样,__iter__被执行后,获取的对象__iter__的返回值,循环返回值返回的对象。
如果类中有这个方法,他创建的对象就叫做可迭代对象,
对于可迭代对象.iter()的返回值,就是迭代器,
对于for循环遇到迭代器,就可以直接进行next()调用
对于foo循环遇到可迭代对象,就需要执行__iter__()先生成迭代器,在进行next()循环。class foo: def __iter__(self): return iter([11,22,33,44]) a = foo() for i in a: print(i) # 11 22 33 44__slots__:限制类对象属性。此限制只存在于此类中,对于他的父类或子类都不受影响。class Foo: __slots__ = ('name', 'age') a = Foo() a.name = 'ming' # 正常向实例对象中插入属性 a.age = 18 # 正常向实例对象中插入属性 a.sex = 'men' # AttributeError: 'Foo' object has no attribute 'sex'__len__:可根据len()函数返回设定值:class Foo: def __len__(self): return 3 a = Foo() print(len(a)) # 3__getattr__:定义一个不存在的属性,当对象调用不存在的属性时,返回对应的内容class Foo: def __init__(self): self.name = 'marry' def __getattr__(self, item): if item == 'sex': return 'women' s = Foo() print(s.name) # marry 存在name属性,取值 print(s.sex) # women 使用__getattr__特殊方法返回属性 注意只有当内容中不存在想要调用的属性时,才会执行__getattr__方法,存在会返回原属性内容 print(s.age) # None 不存在此属性,默认返回None 可以通过raise自定义一个属性不存在报错__instance:创建单列模式;何为创建单列模式,正常的类,每次实例化都会创建一个实例化对象,如果存在__onstance这个私有变量是,该类实列化时,不会创建新的对象,而会将已经创建的实列对象返回,故称之为:单列模式。class Foo: __instance = None def __new__(cls,name,age): # 如果类属性__instance 的值为None 就会创建一个对象,并赋值为这个对象引用,保证下次调用这个方法时,能够知道已经创建对象了,这样就保证了,永远都只存在一个对象 if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance s = Foo('gao',23) s2 = Foo('cao',21) # 打印出两个对象的id可知,地址完全一致,是一个对象 print(id(s)) print(id(s1)) s.age = 19 # 给a对象属性赋值 print(s2.age) # 19__doc__:编写改类的说明文档,可通过help()函数调用
本文详细探讨了Python面向对象编程的高级特性,包括成员修饰符的使用,如公有和私有成员的区别,以及特殊成员如__init__、__new__、__del__等的作用。同时,介绍了如何通过__iter__实现可迭代对象,__slots__限制类属性,__len__自定义长度,以及__getattr__处理未定义属性。
&spm=1001.2101.3001.5002&articleId=105655680&d=1&t=3&u=aed7add9b5d14379947ec5ac66e4f0cf)
1072

被折叠的 条评论
为什么被折叠?



