【Python】 类特殊成员,属性和方法
类的专有方法:
-
__init__ : 构造函数,在生成对象时调用
-
每当创建一个类的实例对象时,Python 解释器都会自动调用构造方法__init__,且 __init__不允许有返回值
# self 参数,每个类对象只能调用自己的类变量和类方法 class eg(object): # 构造函数中的 self 参数,其代表的是当前正在初始化的类对象 def __init__(self): print("pass") pass if __name__ == "__main__": # 创建e 对象 e = eg()
pass 进程已结束,退出代码0
__init__(self,a,b) 存在多个参数
# 创建对象时会调用类的构造方法,如果构造函数有多个参数时,需要手动传递参数 class eg(object): # 类属性就相当与全局变量,实例对象共有的属性 name = 'testname' # 类属性 私有 __age = 12 # 类的构造方法,最少有一个self参数,可以包含多个参数 def __init__(self,a,b): # 传递的参数 self.a = a # 传递的参数 self.b = b # 定义的参数,可以同类中self.c 调用 self.c = 15 # 实例对象的属性为实例对象自己 私有 d = 2 print("构造方法中 计算:a + b = " + str(self.a + self.b) ," c * d = "+ str(self.c * d)) pass # 定义实例方法 def aa(self): print("实例方法 fun(aa) >>> c = ",self.c) print("实例方法 fun(aa) >>> b = ",self.b) if __name__ == "__main__": # 创建实例对象 e = eg(5,3) # 第一种 直接调用类方法 实例化调用函数 print("直接调用类方法") e.aa() # 第二种 函数调用 print("函数调用") ea = e.aa ea() print("类属性name返回 :",e.name) #调用对象中的类属性 print("类方法中的参数 :",e.a) # 调用e中的参数值 e.name = "enametest update" print("实例属性会屏蔽同名的类属性" ,e.name) # 删除实例属性 del e.name print("实例属性被删除后,再调用同名称的属性,会调用类属性" ,e.name)
构造方法中 计算:a + b = 8 c * d = 30 直接调用类方法 实例方法 fun(aa) >>> c = 15 实例方法 fun(aa) >>> b = 3 函数调用 实例方法 fun(aa) >>> c = 15 实例方法 fun(aa) >>> b = 3 类属性name返回 : testname 类方法中的参数 : 5 实例属性会屏蔽同名的类属性 enametest update 实例属性被删除后,再调用同名称的属性,会调用类属性 testname 进程已结束,退出代码0
-
注意:@staticmethod 可以声明一个静态方法,不强制要求传递参数(self);@classmethod 装饰器 也不需要self参数,但第一个参数需要是表示自身类的cls参数
class funa(): def __init__(self): pass # 正常函数 def oro(self): print("oro") @staticmethod # self表示一个类的实例对象本身。如果用了staticmethod就无视这个self了,就将这个方法当成一个普通的函数使用了 def ara(): v = 12 print("method ara") @classmethod # cls表示这个类本身,可以来调用 类的属性,类的方法,实例化对象等 def brb(cls): print("method brb",cls) cls.ara() # 静态调用 cls().oro() # 实例化调用 o = funa() # 常用的调用方法 o.oro() # 实例化调用 funa.ara() # 无需实例化静态调用 funa.brb() # 无需实例化静态调用 print(funa) # 》》》执行结果 # oro # method ara # method brb <class '__main__.funa'> # method ara # oro # <class '__main__.funa'>
-
-
__new__: 是一种负责创建类实例的静态方法
-
__new__() 是一种负责创建类实例的静态方法,它无需使用 staticmethod 装饰器修饰,且该方法会优先 __init__() 初始化方法被调用
class run_case: """临时验证脚本""" def __new__(cls, name, age): """覆写 __new__() 的实现将会使用合适的参数调用其超类的 super().__new__(),并在返回之前修改实例""" print("__new__") return super(run_case, cls).__new__(cls) def __init__(self, name, age): print("__init__") self.name = name self.age = age if __name__ == "__main__": t = run_case("1", "2") print(t)
执行结果
__new__ __init__ <__main__.run_case object at 0x057A59E8> 进程已结束,退出代码为 0
-
super 调用父类的方法
# 单继承,主要是用来调用父类的方法# 父类Aclass A: def __init__(self): self.n = 5 # A类 n=5 def sum(self, m): print('self is {0} @A.sum'.format(self)) # A类sum方法 self.n += m # B类 单继承 A类 class B(A): def __init__(self): self.n = 10 # B类n=10 def add(self, m): print('self is {0} @B.add'.format(self)) # B类add方法 super().sum(m) # 调用父类A的方法 sum n=n+m self.n += 2 # 不调用父类A sum n = n+2 if __name__ == "__main__": a = A() b = B() b.add(10) print("B 类调用方法add(add调用父类A的sum) n = ",b.n) # B 类调用方法add(add调用父类A的sum) n = 22 print("获取 A 类 n值 ",a.n) a.sum(10) print("A 类调用方法sum , n = ",a.n) # A 类调用方法sum , n = 15
self is <__main__.B object at 0x04AC0028> @B.add self is <__main__.B object at 0x04AC0028> @A.sum B 类调用方法add(add调用父类A的sum) n = 22 获取 A 类 n值 5 self is <__main__.A object at 0x04A34F58> @A.sum A 类调用方法sum , n = 15 进程已结束,退出代码0
# 多继承 # 父类A class A: def __init__(self): self.n = 1 # A类 n=5 def sum(self, m): print('self is {0} @A.sum'.format(self)) # A类sum方法 self.n += m # B类 单继承 A类 class B(A): def __init__(self): self.n = 10 # B类n=10 def addb(self, m): print('self is {0} @B.addb'.format(self)) # B类addb方法 super().sum(m) # 调用父类A的方法 sum n=n+m self.n += 2 # 不调用父类A sum n = n+2 # C类 单继承 A类 class C(A): def __init__(self): self.n = 100 def addc(self, m): print('self is {0} @C.addc'.format(self)) # C类addc方法 super().sum(m) # 调用父类A的方法 sum n=n+m self.n += 3 # D类 多继承 B类 C 类 class D(B, C): def __init__(self): self.n = 1000 def addd(self, m): print('self is {0} @D.addd'.format(self)) # D类addd方法 super().sum(m) # 调用父类B/C的父类A的方法 sum n=n+m super().addb(m) # 调用父类B的方法 sum n=n+2 super().addc(m) # 调用父类C的方法 sum n=n+3 self.n += 4 if __name__ == "__main__": a = A() b = B() c = C() d = D() b.addb(20) print("B 类调用方法addb(add调用父类A的sum) n = ",b.n) # B 类调用方法add n = 32 B类addb 调用A类sum print("获取 A 类 n值 ",a.n) a.sum(10) print("A 类调用方法sum , n = ",a.n) # A 类调用方法sum , n = 11 调用A类sum c.addc(30) print("C 类调用方法addc , n = ", c.n) # C 类调用方法sum , n = 133 C类 调用A类 d.addd(40) print("D 类调用方法addd , n = ", d.n) # D 类调用方法sum , n = 1129 D类 调用A类 调用B类(调用A类)调用A类 调用C类(调用A类)
# B self is <__main__.B object at 0x04BD10D0> @B.addb self is <__main__.B object at 0x04BD10D0> @A.sum B 类调用方法addb(add调用父类A的sum) n = 32 获取 A 类 n值 1 # A self is <__main__.A object at 0x04BD10A0> @A.sum A 类调用方法sum , n = 11C # C self is <__main__.C object at 0x04BD1100> @C.addc self is <__main__.C object at 0x04BD1100> @A.sum C 类调用方法addc , n = 133 # A self is <__main__.D object at 0x04BD1130> @D.addd self is <__main__.D object at 0x04BD1130> @A.sum # B self is <__main__.D object at 0x04BD1130> @B.addb self is <__main__.D object at 0x04BD1130> @A.sum #C self is <__main__.D object at 0x04BD1130> @C.addc self is <__main__.D object at 0x04BD1130> @A.sum D 类调用方法addd , n = 1129
-
__del__ : 析构函数,释放对象时使用
- 对象资源被释放时触发,在对象即将被删除时的最后操作
-
# coding:utf-8 from loguru import logger as logs class demo: def __init__(self): """对象资源被创建时调用""" logs.debug("构造函数") def __del__(self): """对象资源被释放时触发,在对象即将被删除时的最后操作""" logs.debug("析构函数") def run(self): logs.debug("run函数") if __name__ == "__main__": demo().run()
执行结果
- 注册析构函数
# coding:utf-8 import xlrd from atexit import register from loguru import logger as logs class demo: def __init__(self): """对象资源被创建时调用""" logs.debug("构造函数") # 注册一个析构函数,拥有与__del__函数同样的效果 register(self.regfun) def __del__(self): """对象资源被释放时触发,在对象即将被删除时的最后操作""" logs.debug("del析构函数") def regfun(self): """被注册的析构函数""" logs.debug("注册的析构函数") def run(self): logs.debug("run函数") if __name__ == "__main__": demo().run()
执行结果
-
<Tips:在del中直接使用open方法,或调用的函数中包含open方法时会报错>
Exception ignored in: <function playThread.__del__ at 0x0B8A8070> …… NameError: name 'open' is not defined
解决方法:将open方法挪到其他位置调用,或者注册析构函数实现
-
__repr__ : 打印,转换
- __repr__() 方法是类的实例化对象用来做“自我介绍”的方法,默认情况下,它会返回当前对象的“类名+object at+内存地址”,对该方法进行重写,可以为其制作自定义的自我描述信息
class run_case: def __init__(self, name, age): print("__init__") self.name = name self.age = age def __repr__(self): """__repr__() 方法是类的实例化对象用来做“自我介绍”的方法[即:制作自定义的自我描述信息] :return: 类名+object at+内存地址 """ return "run_case [name = %s, age = %s]" %(self.name, self.age) if __name__ == "__main__": t = run_case("1", "2") print(t)
执行结果
# 默认 <__main__.run_case object at 0x04B83F10> # __repr__描述后 __init__ run_case [name = 1, age = 2] 进程已结束,退出代码为 0
- __repr__() 方法是类的实例化对象用来做“自我介绍”的方法,默认情况下,它会返回当前对象的“类名+object at+内存地址”,对该方法进行重写,可以为其制作自定义的自我描述信息
-
__str__:
方法需要返回一个字符串,当做这个对象的描写
类似? __repr__
-
__setitem__ : 按照索引赋值
-
__getitem__: 按照索引获取值
-
__delitem__:按照索引删除值
-
# coding:utf-8 class Foo: def __init__(self, name): self.name=name def __getitem__(self, item): print("调用 __getitem__") return self.__dic__[item] def __setitem__(self, key, value): self.__dict__[key]=value print("调用 __setitem__") def __delitem__(self, key): print("调用 __delitem__") self.__dict__.pop(key) def __delattr__(self, item): print("调用 __delattr__") self.__dict__.pop(item) if __name__ == "__main__": f=Foo('sb') print(f.__dict__) #f.age=18 f['age']=18 print(f.__dict__) #f.age1=19 f['age1']=19 print(f.__dict__) del f.age1 print(f.__dict__) del f['age'] print(f.__dict__) f['name'] = 'alex' print(f.__dict__) f['moon'] = "shiliuyuan" print(f.__dict__) print(f.moon)
执行结果
- __len__: 返回容器中元素的个数;即获得长度
# coding:utf-8 from loguru import logger as logs class Demo: def __init__(self, name): self.name=name def __len__(self): logs.info("调用__len__") return len(self.name) class DemoTwo: def __init__(self, name): self.name=name if __name__ == "__main__": # __len__ d = Demo("sunnine") logs.debug(d) logs.debug(d.name) logs.debug(len(d)) logs.debug(len(d.name)) # 无__len__ dt = DemoTwo("lucy") logs.debug(dt) logs.debug(dt.name) logs.debug(len(dt)) logs.debug(len(dt.name))
执行结果:
- __cmp__: 即可实现对实例对象进行排序;即比较运算
- __call__: 函数调用
# coding:utf-8 from loguru import logger as logs class Demo: def __call__(self, a, b): logs.debug(f"调用__call__:{a},{b}") if __name__ == "__main__": dic = [12, 10, 55, 23, 99, 0] d = Demo() d("name", "zhangsan") # 方法一 d.__call__("age", "28")
执行结果:
- __add__: 加运算
# coding:utf-8 from loguru import logger as logs class Demo: def __init__(self): self.f = 2 def __add__(self, other): return other+self.f if __name__ == "__main__": dic = [12, 10, 55, 23, 99, 0] d = Demo() logs.debug(d.__add__(dic[0])) #方法一 logs.debug(d.f.__add__(10)) #方法二
执行结果:
- __sub__: 减运算
- __mul__: 乘运算
- __truediv__: 除运算
- __mod__: 求余运算
- __pow__: 乘方
# coding:utf-8 from loguru import logger as logs class Demo: def __init__(self): self.f = 2 if __name__ == "__main__": dic = [12, 10, 55, 23, 99, 0] d = Demo() logs.debug(d.f.__add__(dic[1])) # 加运算 logs.debug(d.f.__sub__(dic[1])) # 减运算 logs.debug(d.f.__mul__(dic[1])) # 乘运算 logs.debug(d.f.__truediv__(dic[1])) #除运算 logs.debug(d.f.__mod__(dic[1])) # 求余运算 logs.debug(d.f.__pow__(dic[1])) # 乘方
执行结果:
-------------------------------------------------------------------------------------
如果万事开头难 那请结局一定圆满 @ Phoenixy
-------------------------------------------------------------------------------------