python双下方法__汇总
- getattr
class ObjectDict(dict):
def __init__(self, *args, **kwargs):
super(ObjectDict, self).__init__(*args, **kwargs)
def __getattr__(self, name):
value = self[name] # 这种使用没见过
if isinstance(value, dict):
value = ObjectDict(value)
return value
od = ObjectDict(asf={'a': 1}, d=True)
print(od.d) # True,不实现__getattr__,报错 'ObjectDict' object has no attribute 'd'
print(od['d']) # True,不实现__getattr__也可以使用
# 注意
如果有属性self.name,使用od.name的时候不会触发__getattr__ ,只有‘点’不存在属性,才会触发这个方法
- getstate , setstate 【pickle相关】
class Foo(object):
def __init__(self, val=2):
self.val = val
def __getstate__(self):
print("I'm being pickled")
self.val *= 2
return self.__dict__
def __setstate__(self, d):
print("I'm being unpickled with these values: " + repr(d))
self.__dict__ = d
self.val *= 3
import pickle
f = Foo()
f_data = pickle.dumps(f)
f_new = pickle.loads(f_data)
print(f_new.val)
- getiterm/setiterm/deliterm 【[] 运算相关】
class Person(object):
def __init__(self, name):
self.name = name
def __getitem__(self, item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
obj = Person("pd")
ret = obj["name"] # 自动执行 __getitem__ 方法
print(ret) # pd
obj["name"] = "佩奇" # 自动执行 __setitem__ 方法
print(obj["name"]) # 佩奇
del obj["name"] # 自动执行 __delitem__ 方法
# print(obj["name"]) # 报错,KeyError: 'name'
- new/init 【元编程,单例模式等】
https://www.cnblogs.com/amize/p/14599983.html
https://www.cnblogs.com/amize/p/14684780.html
- dict
class Animal(object):
run = True
class Dog(Animal):
fly = False
def __init__(self, age):
self.age = age
def sound(self):
return "wang wang~"
dog = Dog(1)
# 查看dog对象的属性
print ('dog.__dict__:',dog.__dict__)
# 查看类Dog的属性
print ('Dog.__dict__:',Dog.__dict__)
# 查看类Animal的属性
print ('Animal.__dict__:',Animal.__dict__)
#结果 (和dir区别)
#属性在哪个对象上定义,便会出现在哪个对象的__dict__中
'''
dog.__dict__: {'age': 1}
Dog.__dict__: {'__module__': '__main__', 'fly': False, '__init__': <function Dog.__init__ at 0x0000024C426BAB88>, 'sound': <function Dog.sound at 0x0000024C426BA948>, '__doc__': None}
Animal.__dict__: {'__module__': '__main__', 'run': True, '__dict__': <attribute '__dict__' of 'Animal' objects>, '__weakref__': <attribute '__weakref__' of 'Animal' objects>, '__doc__': None}
'''
- str/repr
# 相同的例子
class Test:
pass
print(str(Test()))
print(repr(Test()))
print(str(Test()) == repr(Test()))
#输出结果:
'''
<class '__main__.Test'>
<class '__main__.Test'>
True # 默认情况下一样
'''
# 区别
1. _str_ 用于为最终用户创建输出,而 _repr_ 主要用于调试和开发。 _repr_ 的目标是明确无误,_str_ 是可读的
2. _repr_ 用于推断对象的"官方"字符串表示形式(包含有关对象的所有信息的表示), _str_ 用于推断对象的“非正式”字符串表示形式(对打印对象有用的表示形式)
#再通过一个例子说明问题:
import datetime
today = datetime.datetime.now()
print str(today)
print repr(today)
# 输出结果如下:
'''
2018-08-22 16:52:37.403320
datetime.datetime(2018, 8, 22, 16, 52, 37, 403320)
'''
- name/qualname
- 进阶
- add/sub
- _import_
- _mro_/slot/
get(),set(),delete()
https://www.cnblogs.com/andy1031/p/10923834.html
拥有这个方法的类,应该(也可以说是必须)产生一个实例,并且这个实例是另外一个类的类属性(注意一定是类属性,通过self的方式产生就不属于__get__范畴了)。
也就是说拥有这个方法的类,那么它的实例应该属于另外一个类/对象的一个属性。
非资料描述器,也就是只有__get__,不管是类还是实例去访问,默认都获得的是__get__的返回值,但是,如果中间有任何一次重新赋值,那么,这个实例获得的是新的值(对象),已经和原来的描述器完全脱离了关系
资料描述器,比如有__set__方法,后期通过实例对描述器进行赋值,那么访问的是__set__,并且永远关联起来。但是如果通过修改类属性的方式复制,那么也会被重新获取新的值(对象)。
# __get__ 的使用
class TestDes:
def __get__(self, instance, owner):
print(instance, owner)
return 'TestDes:__get__'
class TestMain:
des = TestDes()
if __name__ == '__main__':
t = TestMain()
print(t.des)
print(TestMain.des)
# __get__ __set__ 的使用
class TestDes:
def __get__(self, instance, owner):
print('TestDes:__get__:', instance, owner)
return 'TestDes:__get__return'
def __set__(self, instance, value):
print('TestDes:__set__:', instance, value)
class TestMain:
des = TestDes()
if __name__ == '__main__':
t = TestMain()
print(t.des)
print(TestMain.des)
print('*************************')
t.des = 1
print(t.des)
print(TestMain.des)
print('*************************')
TestMain.des = 1
print(t.des)
print(TestMain.des)
'''
TestDes:__get__: <__main__.TestMain object at 0x06C04C70> <class '__main__.TestMain'>
TestDes:__get__return
TestDes:__get__: None <class '__main__.TestMain'>
TestDes:__get__return
*************************
TestDes:__set__: <__main__.TestMain object at 0x06C04C70> 1
TestDes:__get__: <__main__.TestMain object at 0x06C04C70> <class '__main__.TestMain'>
TestDes:__get__return
TestDes:__get__: None <class '__main__.TestMain'>
TestDes:__get__return
*************************
1
1
'''
#描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
#描述符Int
class Int:
def __get__(self, instance, owner):
print('Int调用')
def __set__(self, instance, value):
print('Int设置...')
def __delete__(self, instance):
print('Int删除...')
class People:
name=Str()
age=Int()
def __init__(self,name,age): #name被Str类代理,age被Int类代理,
self.name=name
self.age=age
#何地?:定义成另外一个类的类属性
#何时?:且看下列演示
p1=People('alex',18)
#描述符Str的使用
p1.name
p1.name='egon'
del p1.name
#描述符Int的使用
p1.age
p1.age=18
del p1.age
#我们来瞅瞅到底发生了什么
print(p1.__dict__)
print(People.__dict__)
#补充
print(type(p1) == People) #type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)
- 高级
- call
- iter
- enter/exit
- metaclass
- 双下"_ _"方法汇总一下
-
- 基础
- getattr/setattr/delattr、getattribute
定义了__getattr__(),当访问object不存在的属性时会调用该方法
不定义访问不存在的属性时会报 AttributeError