python双下方法__汇总

  1. 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__ ,只有‘点’不存在属性,才会触发这个方法

  1. 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)

  1. 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'
  1. new/init 【元编程,单例模式等】
https://www.cnblogs.com/amize/p/14599983.html
https://www.cnblogs.com/amize/p/14684780.html
  1. 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}
'''

  1. 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)
'''

  1. name/qualname

  1. 进阶
  • 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__)
  1. 高级
  • call

  • iter

  • enter/exit

  • metaclass

  1. 双下"_ _"方法汇总一下
    1. 基础
  • getattr/setattr/delattrgetattribute

定义了__getattr__(),当访问object不存在的属性时会调用该方法
不定义访问不存在的属性时会报 AttributeError

posted @ 2021-04-21 18:12  该显示昵称已被使用了  阅读(51)  评论(0编辑  收藏  举报