python面向对象之数据和自省(私有属性、内置属性、自定义属性和描述器)
一、私有属性
- 类里面定义的变量叫类属性,类属性有两种:公有属性和私有属性
- 私有属性定义:
单下划线开头:_attr
双下划线开头:__attr
python中并未实现属性的真正私有化,但可以用下划线实现伪私有。
class MyClass(): attr1="attr1" _attr2="attr2" __attr3="attr3" m=MyClass() #访问公有属性 print(MyClass.attr1) print(m.attr1) #访问单下划线私有属性 print(MyClass._attr2) print(m._attr2) #访问双划线私有属性 print(MyClass._MyClass__attr3) #访问私有属性需要在属性名称前面加上"_类名" print(m._MyClass__attr3) print(MyClass.__dict__) #查看该类的所有属性和方法
运行结果:
attr1 attr1 attr2 attr2 attr3 attr3 {'__module__': '__main__', 'attr1': 'attr1', '_attr2': 'attr2', '_MyClass__attr3': 'attr3', '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}
二、__dict__
类调用__dict__属性,返回类的属性和方法的字典。
实例调用__dict__属性,返回实例相关的属性和方法。
class MyClass(): attr1="attr1" def __init__(self,name): self.name=name def test(self): print("这是一个test方法") m=MyClass("crystal") print(m.__dict__) #运行结果: {'name': 'crystal'} print(MyClass.__dict__) #运行结果:{'__module__': '__main__', 'attr1': 'attr1', '__init__': <function MyClass.__init__ at 0x10f8460d0>, 'test': <function MyClass.test at 0x10f846158>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}
三、内置属性__slots__
默认情况下,类的实例有一个字典用于存储属性,这对于具有很少实例变量的对象会浪费空间。当创建大量实例时,空间消耗会很大。
可以通过在类定义中定义__slots__来覆盖默认__dict__行为。
class Base(object): #指定类对象所能绑定的属性 #限制属性 #节约内存,定义了__slots__属性后,那么该对象不会再自动生成__dict__属性 __slots__ = ['name'] pass b=Base() # b.age="20" # 'Base' object has no attribute 'age' b.name="crystal" # print(b.__dict__) #'Base' object has no attribute '__dict__'
四、自定义属性访问
可以定义下面的方法来访问、赋值或删除自定义类实例。
- object.__getattr__:当查找不到属性,触发AttributeError异常时会调用此方法
- object.__getattribute__:查找属性时,第一时间会调用此方法
- object.__setattr__:设置属性时,调用此方法给属性赋值
- object.__delattr__:删除属性时触发此方法
(1)获取属性方法
class Test: def __getattr__(self, item): print("这是__getattr__方法") return 100 def __getattribute__(self, item): print("这是__getattribute__方法") return super().__getattribute__(item) t=Test() t.name=999 print(t.name) print("-------------------") print(t.name1)
运行结果:
这是__getattribute__方法 999 ------------------- 这是__getattribute__方法 这是__getattr__方法 100
(2)设置属性方法
class Test: def __setattr__(self, key, value): #此方法在给对象设置属性时会触发 print("这是__setattr__方法") if key=="age": super().__setattr__(key, 18) else: super().__setattr__(key,value) t=Test() t.name=999 print(t.name) print("-------------------") t.age=200 print(t.age)
运行结果:
这是__setattr__方法 999 ------------------- 这是__setattr__方法 18
(3)删除对象属性方法
class Test: def __delattr__(self, item): print("这是__delattr__方法") super().__delattr__(item) t=Test() t.name=999 print(t.name) print("--------------") del t.name print(t.name)
运行结果:
999 -------------- 这是__delattr__方法 Traceback (most recent call last): File "/Users/grace/PycharmProjects/selenium/test.py", line 375, in <module> print(t.name) AttributeError: 'Test' object has no attribute 'name'
五、描述器
描述器是一个具有绑定行为的对象属性,如果一个对象定义以下方法中的任何一个,它被称为描述器。
object.__get__(self,instance,owner):获取属主类的属性或者该类的一个实例的属性。
object.__set__(self,instance,value):设置属主类实例的属性的值
object.__delete(self,instance,value):删除属主类实例的属性。
实例:
class Field: def __get__(self, instance, owner): print("__get__方法被触发") print("owner:", owner) #属主类:<class '__main__.Model'> return self.value def __set__(self, instance, value): print("__set__方法被触发") print("self:", self) #描述器的实例:<__main__.Field object at 0x1128d3048> print("instance:", instance) #属主类的实例: <__main__.Model object at 0x1128d3080> print("value:", value) self.value=value def __delete__(self, instance): print("__delete__方法被触发") del self.value class Model(object): name="musen" attr=Field() m=Model() m.attr=10 print("-----------") print(m.attr) print("-------------") del m.attr
运行结果:
__set__方法被触发 self: <__main__.Field object at 0x10679e080> instance: <__main__.Model object at 0x10679e0f0> value: 10 ----------- __get__方法被触发 owner: <class '__main__.Model'> 10 ------------- __delete__方法被触发
使用描述器实现ORM模型中的字段类型: 参考https://www.cnblogs.com/crystal1126/p/13625306.html
posted on 2020-08-28 13:00 crystal1126 阅读(254) 评论(0) 编辑 收藏 举报