Python 属性方法、类方法、静态方法、 特殊属性__doc__ (内建属性)
总结:和类的关联性讲:属性方法>类方法>静态方法
属性方法@property:仅仅是调用方式不用+括号。
类方法@classmethod:访问不了累的属性变量,只可以访问类变量。
静态方法@staticmethod:仅仅是通过类名来调用这个函数而已,和类本身已经没有功能关系了,严格讲已经不是类的方法而是一个通过类名调用的函数而已(无法访问实例化的类的任何属性过着其他方法)。
在类中的方法加如下装饰器
属性方法:@property将方法变为类的一个静态属性,调用的时候无需加括号。对外隐藏实现细节,对于用户来讲,感觉就是在查一个写死的
class Flight(object): def __init__(self,name): self.name = name # flight_status def check_flight(self): print('checking flight %s: status'% self.name) status = 3 return status @property #为类的一个静态属性,调用的时候无需加括号。对外隐藏实现细节,对于用户来讲,感觉就是在查一个写死的静态属性 def flight_status(self): status = self.check_flight if status == 0: print('flight got canceled...') elif status == 1: print('flight is arrived...') elif status == 2: print('flight has departured already...') else: print('cannot confirm the flight status ....please check later') @flight_status.setter #对属性方法里面的参数进行修改 def flight_status(self,status): self.check_flight = status status_dict = { 0:'canceled', 1:'arrived', 2:'departured' } print('\033[31;1mhas changed flight:%s status to:%s\033[0m'%(self.name,status_dict[status])) @flight_status.deleter #加上删除装饰器,这个静态方法就可以被删除 def flight_status(self): print('status Func got removed') f1 = Flight("川航3U8633") f1.flight_status #不用加括号 f1.flight_status = 1 f1.flight_status del f1.flight_status f1.flight_status
静态方法:@staticmethod
只是名义上归类管理,实际上在静态方法里访问不了类或者实例的任何属性
class Dog(object): def __init__(self,name): self.name = name def talk(self): print('%s talking: 旺旺旺!'% self.name) @staticmethod def eat(self,food): print('%s eating %s'%(self.name,food)) d1 = Dog('ChenRonghua') d1.eat('包子')
Traceback (most recent call last): File "C:/Users/Administrator/Desktop/Python3_study/day6/静态方法_类方法.py", line 15, in <module> d1.eat('包子') TypeError: eat() missing 1 required positional argument: 'food'
类方法:@classmethod
只能访问类变量,不能访问实例变量
class Dog(object): name = '类方法调用测试用类变量' def __init__(self,name): self.name = name def talk(self): print('%s talking: 旺旺旺!'% self.name) # @staticmethod @classmethod def eat(self,food): print('%s eating %s'%(self.name,food)) d1 = Dog('ChenRonghua') d1.eat('包子')
类方法调用测试用类变量 eating 包子 Process finished with exit code 0
类的内置方法__doc__
class Dog(object): '''描述一个狗的样子''' pass print(Dog.__doc__)
输出:描述一个狗的样子
类的内置方法__module__;__class__
class C(object): pass
from lib import test obj = test.C() print(obj.__module__) print(obj.__class__)
输出结果 lib.test <class 'lib.test.C'>
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Dog(object): name = '类方法调用测试用类变量' def __init__(self,name): self.name = name # def talk(self): # print('%s talking: 旺旺旺!'% self.name) # # @staticmethod # @classmethod # def eat(self,food): # print('%s eating %s'%(self.name,food)) def __call__(self, *args, **kwargs): print("我了个__call__") d1 = Dog('ChenRonghua') d1() 输出:我了个__call__
6.__dict__ 查看类或对象中的所有成员变量
class Dog(object): name = '类方法调用测试用类变量' def __init__(self,name): self.name = name def __call__(self, *args, **kwargs): print("我了个__call__") d1 = Dog('ChenRonghua') print(d1.__dict__) print(Dog.__dict__)
输出: {'name': 'ChenRonghua'} {'__module__': '__main__', 'name': '类方法调用测试用类变量', '__init__': <function Dog.__init__ at 0x0000002A9CE32AE8>, '__call__': <function Dog.__call__ at 0x0000002A9CE32B70>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class Dog(object): def __str__(self): return "我是类中__str__方法 return的字符串" def __init__(self,name): self.name = name d1 = Dog('ChenRonghua') print(d1) 输出:我是类中__str__方法 return的字符串
8.__getitem__、__setitem__、__delitem__
用于索引操作,如过一个类的属性中有类似字典格式的数据。以上内置方法 分别表示获取、设置、删除 该类实例化的实例属性中的数据
class Foo(object): def __init__(self): self.data = {} def __setitem__(self, key, value): self.data[key] = value def __getitem__(self, key): return self.data.get(key) #字典的get(key)方法,不会因为没有key报错 def __delitem__(self, key): print('\033[32;1m你让我删,我就删啊\033[0m') del self.data[key] obj = Foo() obj['name'] = 'zhangmingda' #自动触发执行__setitem__(self, key, value): obj['age'] = 23 print(obj.data) value = obj['age'] #自动触发执行__getitem__(self, key): print(value) del obj['age'] #自动触发执行__delitem__(self, key):
{'name': 'zhangmingda', 'age': 23} 23 你让我删,我就删啊 Process finished with exit code 0
类的起源:type
def func(self): print('我是类的方法,不是函数') def __init__(self,name,age): self.name = name self.age = age Foo = type('Foo',(object,),{'func':func,'__init__':__init__})#定义一个类的原始写法'func'和'__init__'为类的方法名 f1 = Foo('zhangmingda',23) f1.func() print(f1.name,f1.age)
我是类的方法,不是函数
zhangmingda 23
自定义一个原类 :__metaclass__
__metaclass__:作用-->定义一个类创建的过程
class MyType(type): def __init__(self,*args,**kwargs): print("Mytype __init__",*args,**kwargs) def __call__(self, *args, **kwargs): print("Mytype __call__", *args, **kwargs) obj = self.__new__(self) print("obj ",obj,*args, **kwargs) print(self) self.__init__(obj,*args, **kwargs) return obj def __new__(cls, *args, **kwargs): print("Mytype __new__",*args,**kwargs) return type.__new__(cls, *args, **kwargs) print('here...') class Foo(object,metaclass=MyType): # __metaclass__ = MyType def __init__(self,name): self.name = name print("Foo __init__") def __new__(cls, *args, **kwargs): #new的作用,将类实例化。没有new,__init__(self)构造函数不会执行 print("Foo __new__",cls, *args, **kwargs) return object.__new__(cls) #继承原类 f = Foo("Alex") print("f",f) print("fname",f.name)
内建属性__init__ ; __getattribute__
子类没有实现__init__
方法时,默认自动调用父类的。 如定义__init__
方法时,需自己手动调用父类的 __init__
方法
常用专有属性 | 说明 | 触发方式 |
---|---|---|
__init__ |
构造初始化函数 | 创建实例后,赋值时使用,在__new__ 后 |
__new__ |
生成实例所需属性 | 创建实例时 |
__class__ |
实例所在的类 | 实例.__class__ |
__str__ |
实例字符串表示,可读性 | print(类实例),如没实现,使用repr结果 |
__repr__ |
实例字符串表示,准确性 | 类实例 回车 或者 print(repr(类实例)) |
__del__ |
析构 | del删除实例 |
__dict__ |
实例自定义属性 | vars(实例.__dict__) |
__doc__ |
类文档,子类不继承 | help(类或实例) |
__getattribute__ |
属性访问拦截器 | 访问实例属性时 |
__bases__ |
类的所有父类构成元素 | 类名.__bases__ |
__getattribute__
例子:
class Itcast(object): def __init__(self,subject1): self.subject1 = subject1 self.subject2 = 'cpp' #属性访问时拦截器,打log def __getattribute__(self,obj): if obj == 'subject1': print('log subject1') return 'redirect python' else: #测试时注释掉这2行,将找不到subject2 return object.__getattribute__(self,obj) def show(self): print('this is Itcast') s = Itcast("python") print(s.subject1) print(s.subject2) #运行结果: log subject1 redirect python cpp
__getattribute__的坑
class Person(object): def __getattribute__(self,obj): print("---test---") if obj.startswith("a"): return "hahha" else: return self.test def test(self): print("heihei") t.Person() t.a #返回hahha t.b #会让程序死掉 #原因是:当t.b执行时,会调用Person类中定义的__getattribute__方法,但是在这个方法的执行过程中 #if条件不满足,所以 程序执行else里面的代码,即return self.test 问题就在这,因为return 需要把 #self.test的值返回,那么首先要获取self.test的值,因为self此时就是t这个对象,所以self.test就是 #t.test 此时要获取t这个对象的test属性,那么就会跳转到__getattribute__方法去执行,即此时产 #生了递归调用,由于这个递归过程中 没有判断什么时候推出,所以这个程序会永无休止的运行下去,又因为 #每次调用函数,就需要保存一些数据,那么随着调用的次数越来越多,最终内存吃光,所以程序 崩溃 # # 注意:以后不要在__getattribute__方法中调用self.xxxx
posted on 2018-06-10 10:35 zhangmingda 阅读(184) 评论(0) 编辑 收藏 举报