pytho的魔术方法之属性

特殊属性

属性说明
__name __类、函数、方法等的名字,实例没有__name__的属性
__module __类定义所在的模块名
__class __对象或类所属的类
__bases __类的基类的元组,顺序为它们在基类列表中出现的顺序
__doc __类、函数的文档字符串,如果没有定义则为 None
__mro __类的mro,class.mro()返回的结果的保存在 __mro __
__dict __类或实例的属性,可写的字典

`

查看属性

__dir __ 方法

方法说明
__dir __返回类或者对象的所有成员 名称列表。通过内建函数 dir() 操作实例就是调用 __dir __()。

如果dir([obj])参数obj包含方法__dir__(),该方法将被调用。如果参数obj不包含__dir__(),该方法将最大限度地收集属性信息。

  • dir(obj)对于不同类型的对象obj具有不同的行为:

    • 如果对象是模块,返回的列表包含模块的属性名和变量名
    • 如果对象是,返回的列表包含类的属性名,及它的祖先类的属性名
    • 如果是类的实例
      • 有__dir__方法,返回可迭代对象的返回值
      • 没有__dir__方法,则尽可能收集实例的属性名、类的属性和祖先类的属性名
  • 如果dir([obj])中的obj不写,则分3种情况

    • 在模块中,返回模块的属性和变量名
    • 在函数中,返回本地作用域的变量名
    • 在方法中,返回本地作用域的变量名
  • dir 方法一定要返回一个可迭代对象

  • 不管__dir__ 方法返回的是什么要的可迭代对象,最终都会被解释器转换为一个列表

class Animal:
    def __init__(self,name):
        self.name = name

cat = Animal('cat')
print(dir(cat))       # 该方法将最大限度地收集属性信息,返回的列表包含类的属性名,及它的祖先类的属性名
-------------------------------------
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
class Animal:
    def __init__(self,name):
        self.name = name

    def __dir__(self):
        return ['a','b']    #必须返回可迭代对象

cat = Animal('cat')
print(dir(cat))
------------------------------------
['a', 'b']

__dir __() 方法测试

class Person:
    def show(self):  # 方法中
        a = 100
        t = int(a)
        print(dir())    #返回变量字典,形参也是变量
        print(locals())  #返回字典


def test(a=50, b=100):  # 函数中
    c = 150
    print(dir())
    print(locals())
    print(globals())


Person().show()
test()
print(dir())
-------------------------------------------------------------------------------
['a', 'self', 't']
{'self': <__main__.Person object at 0x000001A581F4DAC8>, 'a': 100, 't': 100}
['a', 'b', 'c']
{'a': 50, 'b': 100, 'c': 150}
['Person', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'test']
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000220A1AE6668>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/pycharm/test/Animal.py', '__cached__': None, 'Person': <class '__main__.Person'>, 'test': <function test at 0x00000220A38F2378>}


内建函数

  • locals() 返回当前作用域中的变量字典
  • globals() 当前模块全局变量的字典

魔术方法

魔术方法的分类

  • 创建、初始化与销毁 __new __ 、__init __ 、__del __
  • hash
  • bool
  • 可视化
  • 运算符重载
  • 容器和大小
  • 可调用对象
  • 上下文管理
  • 反射
  • 描述器
  • 其他杂项

实例化
方法意义
__new __实例化一个对象,该方法需要返回一个值,如果该值不是cls的实例,则不会调用__init__该方法永远都是静态方法
class Person:    
    def __new__(cls, *args, **kwargs):
        print(cls)
        print(args)
        print(kwargs)
        return None    
    
    def __init__(self, name):
        self.name = name

tom = Person("tom")
print(tom)
----------------------------------------------------
<class '__main__.Person'>
('tom',)
{}
None
  • __new__方法很少使用,即使创建了该方法,也会使用return super().new(cls)基类object的__new__方法来创建实例并返回

可视化
方法意义
__str __str()函数、format()函数、print()函数调用,需要返回对象的字符串表达。如果没有定义,就去调用__repr__方法返回字符串表达,如果__repr__没有定义,就直接返回对象的内存地址信息
__repr __内建函数repr()对一个对象获取字符串表达。调用__repr__方法返回字符串表达,如果__repr__也没有定义,就直接返回object的定义就是显示内存地址信息
__bytes __bytes()函数调用,返回一个对象的bytes表达,即返回bytes对象
  • 使用方法如下
class Person:

    def __init__(self, name, age=18):
        self.name = name
        self.age = age

    def __repr__(self):
        return 'repr: {},{}'.format(self.name, self.age)

    def __str__(self):
        return 'str:  {},{}'.format(self.name, self.age)

    def __bytes__(self):
        return "{} is {}".format(self.name, self.age).encode()

tom = Person('tom')
print(tom)  # print函数使用__str__
print('{}'.format(Person('tom')))
print([Person('tom')])  # []使用__str__,但其内部使用__repr__
print(tom.__dict__)
----------------------------------------------------
str:  tom,18
str:  tom,18
[repr: tom,18]
{'name': 'tom', 'age': 18}

hash
方法意义
__hash __内建函数hash()调用的返回值,返回一个整数。如果定义这个方法该类的实例就可hash。
__eq __对应==操作符,判断2个对象是否相等,返回bool值定义了这个方法,如果不提供__hash__方法,那么实例将不可hash了
class Person:

    def __init__(self, name, age=18):
        self.name = name
        self.age = age

    def __hash__(self):
        return 100
        
A = Person('tom')
tom = Person('tom')
print(hash(tom),hash(A))  ##两个对象的哈希值相同,都为设定的100
print({A,tom})            ## hash 值相同,但是并不能去重
----------------------------------------------------
100 100
{<__main__.Person object at 0x0000014463288358>, <__main__.Person object at 0x0000014462F86710>}

要去重,必须还要相等,如下

class Person:

    def __init__(self, name, age=18):
        self.name = name
        self.age = age

    def __hash__(self):
        return 100

    def __eq__(self, other):  # 这个函数作用就是判断个实例是否相等,相等返回 True,不等返回 False
        return self.name == other.name
        
print(hash(tom),hash(A))  ##两个对象的哈希值相同,都为设定的100 ,设为相同
print({A,tom})   # hash 值相同,并且通过__eq__判断内容相等,就会进行去重处理
----------------------------------------------------       
100 100
{<__main__.Person object at 0x000002BA70E46710>}
  • 去重必须要满足 hash值一样,并且内容相等

方法意义
__ bool__内建函数bool(),或者对象放在逻辑表达式的位置,调用这个函数返回布尔值。没有定义__bool__(),就找__len__()返回长度,非0为真。如果__len__()也没有定义,那么所有实例都返回真

运算符
特殊方法含义
<, <=, ==, >, >=, !=__lt __, __le __, __eq __, __gt __, __ge __, __ne __比较运算符
+, -, *, /, %, //, **, divmod__add __, __sub __, __mul __, __truediv __, __mod __, __floordiv __, __pow __, __divmod __算数运算符,移位、位运算也有对应的方法
+=, -=, *=, /=, %=, //=, **=__iadd __, __isub __, __imul __, __itruediv __, __imod __, __ifloordiv __, __ipow __
  • 实现Point类的2个实例相加,减
class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y
        
    def __add__(self,other):
        return (self.x + other.x , self.y + other.y)
    
    def __sub__(self,other):
        return (self.x - other.x , self.y - other.y)
    
    def __str__(self):
        return str((self.x, self.y))

p1 = Point(2,3)
p2 = Point(5,6)
print(p1+p2)
print(p1-p2)
------------------------------------------------------------------------
(7, 9)
(-3, -3)

__ isub __方法定义,一般会in-place就地来修改自身如果没有定义__isub__方法,则会调用__sub __

class Person: 
    def __init__(self, name, age):
        self.name = name
        self.age = age 

    def __eq__(self, other):           # __eq__等于可以推断不等于
        return self.age == other.age  

    def __gt__(self, other):           # __gt__大于可以推断小于
        return self.age > other.age  

    def __ge__(self, other):           # __ge__大于等于可以推断小于等于
        return self.age >= other.age
    
tom = Person('tom', 20)
jerry = Person('jerry', 16)
print(tom > jerry)     >>>True
print(tom < jerry)     >>>False
print(tom >= jerry)    >>>True
print(tom <= jerry)    >>>False
print(tom == jerry)    >>>False
print(tom != jerry)    >>>True

容器相关方法
方法意义
__len __内建函数len(),返回对象的长度(>=0的整数),如果把对象当做容器类型看,就如同list或者dict。bool()函数调用的时候,如果没有__bool__()方法,则会看__len__()方法是否存在,存在返回非0为真
__iter __迭代容器时,调用,返回一个新的迭代器对象
__contains __in 成员运算符,没有实现,就调用__iter__方法遍历
__getitem __实现self[key]访问。序列对象,key接受整数为索引,或者切片。对于set和dict,key为hashable。key不存在引发KeyError异常
__setitem __和__getitem__的访问类似,是设置值的方法
__missing __字典或其子类使用__getitem__()调用时,key不存在执行该方法
#伪装成容器,必须具备容器的一些特征,如: iter(),len(),get(),set()

class Cart:
    def __init__(self):
        self.items = []      #用list设定一个伪装容器
    
    def additem(self,item):
        self.items.append(item)
        return self
    
    def __len__(self):                  #给容器增加一个判断长度的功能
        return len(self.items)
    
    def __getitem__(self,index):        #给容器增加一个用索引查找的功能
        return self.items[index] 

    def __setitem__(self,key,value):    #给容器增加一个元素重新赋值的功能
        return self.items[key] == value
    
    def __iter__(self):                 #将容器变为可迭代器
        return iter(self.items)
    
    def __add__(self,other):            #给容器增加一个增加元素的功能
        self.items.append(other)
        return self
    
    def __str__(self):
        return str(self.items)
        
p1 = Cart()
p1.additem('cup')
p1.additem('phone').additem('keyboard')
print(p1)
-----------------------------------------------------------
['cup', 'phone', 'keyboard']

可调用对象
方法意义
__call __类中定义一个该方法,实例就可以像函数一样调用

举例:累加

class Add:

    def __call__(self, *args):
        ret = 0
        for i in args:
            ret += i
            self.ret = ret
        return self.ret

adder = Add()
print(adder(1,2,3))
----------------------------------
6
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值