python类的魔法方法基础

参考:小甲鱼视频

作用:对类进行“刷机”级的修改

魔法方法的标志:①被__xxx__两条下划线包围:如典型的__init__

1.__init__(self,....)

问:在定义类的时候,为什么有的时候有这个魔法方法,有的时候没有呢?

答:一般都会有,但是如果不需要传入类的属性参数,那么就不需要有啊

另外注意 在__init__方法的里面不可以写return返回任何东西

2.__new__(self,...) 类里面最先执行的魔法方法,比__init__还先,注意他的参数和init 的参数一模一样!!!

一般很少修改,但是有一种情况下:

>>> class Calstr(str):
	def __new__(cls,string):   #在这里  cls的位置是填str类的别名可以随意取,不构成参数,第二个string参数则特质str类里的传入字符串不能改
		string=string.upper()
		return str.__new__(cls,string)  # 改变父类的__new__   参数string 同时也是 __init__(self,string)的参数

	
>>> a=Calstr('aaaaaa')
>>> a
'AAAAAA'

①优先运行:这里看到运行Calstr()就自动执行new方法了,不用a.__new__什么的。

②重写不可改变的方法:继承str这个不可改变的类,所以不可以在init里修改str类,但是我们可以在之前的new里面重写 返回新的   str.__new__(  )这个方法执行的结果。也可以在参数赋值给init属性之前,判断参数是不是合理的先行函数。

③_注意在使用new方法的时候,调用了父类的new方法,并且返回了这个值,使用return语句

当不使用return的时候,那么此值会变成为None,也就是默认情况下返回值为None。

3. python无处不对象,内置的工厂函数就可以被重新定义:

python类的魔法方法基础_第1张图片

>>> class new_int(int):
           def __add__(self,other):  #当有__add__的类遇到+自动调用此方法 因为+ 就是__add__魔法方法
               return int.__sub__(self,other)  # 这里一定要加 int.

        
>>> a =new_int(2)
>>> b=a+1
>>> b
1
>>> #这里说明类内置工厂函数的使用方式

反运算:

内置工厂函数每个都有__radd__,__rsub__等对应的反运算函数,它表示在a + b的过程中如果a类里面没有定义 +操作,自动转向b,就相当于 b+a

>>> class new_int(int):
           def __radd__(self,other):  #当有__add__的类遇到+自动调用此方法 因为+ 就是__add__魔法方法
               return int.__sub__(self,other)  # 这里一定要加 int.

        
>>> 1 + new_int(2)             #  1    就是一个数,不是一个类,所以它自己没有 +方法  但是我又发现int(1)+new_int(2)=1  why???
1
回答:官方文档指出下面两种情况调用:
1. 左操作数不支持相关运算 并且 两个操作数是不同类型时才被调用。(好像后半句是废话)
2.如果右操作数的类型是左操作数类型的子类,并且该子类提供了操作的反射方法,反射方法优先使用!!!(最新官方文档)

4. 属性访问

  • 访问属性的时候,比如你定义了C类 可以用,c=C()实例化,再用c.x就可以访问c实例里的属性x的值。

另外:getattr(c,’x‘,'如果没有这个属性就显示这里的字符串')  绅士的访问。

  • 通过property 让外部的设置函数保持不变,比如,如果我在内部更改了getSize的名字,外部调用时也得改,如果我把它付给x(应该是原来的名字),就可以不改变了。
  • python类的魔法方法基础_第2张图片
  • property的作用就是把一个普通类里面 针对某个属性修改的函数,作为参数,形成的property类。这个类赋值给x,就可以
  • 把x和原有的属性联系起来!!
  • 访问属性之前的魔法方法:
  • python类的魔法方法基础_第3张图片python类的魔法方法基础_第4张图片

以上示例说明访问任何属性之前,都会先执行以上函数。参数都是接受你写入的参数或者值(setattr)

另外:在附加完操作之后,还需要继承Object的属性。

描述符

python类的魔法方法基础_第5张图片

property函数是python标准的描述符,我们也可以自定义自己的描述符(至少含有上面三个函数的一个):

下面代码就是property的原理:

# propperty 描述符到底是怎么实现的??
#它其实也是一个类
class my_property():                      #针对一个属性的控制类
    
    def __init__(self,get,set1,delete_):  #给这个类输入 获取、修改、删除 等原来针对这个属性操作的方法名字
        self.get=get
        self.set1=set1
        self.delete=delete_

    def __get__(self,instance,owner):     #在这里可以就是把原来类的修改函数和工厂函数联系起来而__get__下的self.get等形式就是调用原来的方法
        return self.get(instance)
                                          #但要注意这里的instance参数是必须要加上的。
    def __set__(self,instance,value):
        self.set1(instance,value)    ##
        print(instance,value)

    def __delete__(self,instance):
        self.delete_(instance)


class C():
    def __init__(self):
        self._x=None
        
    def get(self):
        return self._x


    def set1(self,value):  #  对_x属性为什么不直接修改呢?还弄个set1函数修改。。
        self._x=value      # 因为 如果你要限制_x的范围,直接修改你怎么限制,必然是把x设置为私有变量_x再去设置一个函数,去专门修改它。

    def delete_(self):
        del self._x

    x =my_property(get,set1,delete_)   #把本来直接修改不能控制范围的缺点,通过设置专门的函数,并把函数还给了原有的属性,是从简单--复杂--简单
##                                          这就是property的巨大作用
c=C()
c.x='哈哈哈'

你可能感兴趣的:(数据结构基础)