静态方法
截断了类和方法的内在联系。 只是名义上归类管理,实际上在静态方法里访问不了类或者实例中的任何属性。
class Dog(object): def __init__(self, name): self.name = name @staticmethod # 静态方法截断了类和方法的联系。 和在类外设置函数是一样的。 def eat(self): print('%s is earting bum ' %(self.name)) d = Dog("Rory") d.eat()
返回错误结果如下:
Traceback (most recent call last): File "/Users/PycharmProjects/learningnote/moduel3/OPP进阶 - 静态方法.py", line 18, in <module> d.eat() TypeError: eat() missing 1 required positional argument: 'self'
类方法
只能访问类变量,不能访问实例变量。
class Dog(object): name = "marlynda" def __init__(self, name): self.name = name @classmethod # 类方法 def eat(self): print('%s is earting bum' % self.name) d = Dog("Rory") d.eat() # 在类方法下, 调用的self.name是类变量
返回结果:
marlynda is earting bum
属性方法
@property
将一个方法变成一个静态属性,即调用是不用加()
。
class Dog(object): name = "marlynda" def __init__(self, name): self.name = name @property def eat(self): print('%s is earting bum' % self.name) d = Dog("Rory") d.eat
当该方法原来有参数时,改写方式应该如下:
class Dog(object): name = "marlynda" def __init__(self, name): self.name = name self.__food = None # 3. 添加私有属性__food @property # 1. 设置属性方法,将方法转变为静态属性 def eat(self): print('%s is eating %s' % (self.name, self.__food)) @eat.setter # 2. 另增加一个同为eat的方法,并增加参数food def eat(self, food): print("set the food:", food) self.__food = food # 4. 传入参数,更新私有属性__food @eat.deleter # 5. 作为属性, 单纯调用 del d.eat,是删不掉。需要再写个@eat.deleter def eat(self): del self.__food print("删完了") d = Dog("Rory") d.eat d.eat = "bum" d.eat d.eat = "beef" d.eat del d.eat
返回结果
Rory is eating None set the food: bum Rory is eating bum set the food: beef Rory is eating beef 删完了
属性方法在实际情况中,比较有用。很多场景中是不能简单通过定义静态属性来实现的。
比如,类似像飞常准这样的平台,获取一个航班的当前状态(到达,延迟,取消,还是飞走等), 需要经历以下几步:
- 链接航空公司提供的API接口:可能是json, xml等
- 对查询结果进行解析
- 返回结果给你的用户
获取这些status其实是一系列动作的结果,但是客户不关心,他们只需要这系列动作后的结果即可。
class Fight(object): def __init__(self, name): self.flight_name = name def checking_status(self): print('checking flight %s status' % self.flight_name) return 1 @property def flight_status(self): status = self.checking_status() if status == 0: print('flight got cancelled...') elif status == 1: print("flight has 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): print("flight %s has change status to %s" %(self.flight_name, status)) f = Fight("CA980") f.flight_status f.flight_status = "2" f.flight_status
返回信息
checking flight CA980 status flight has arrived... flight CA980 has change status to 2 checking flight CA980 status flight has arrived...
特殊成员方法
特殊方法一般主要实现模拟标准类型和重载操作符。
1. __doc__
现实类的描述信息, 调用如下 print(Foo.__doc__)
2. __module__
和 __class__
__module__
表示当前操作的对象在哪个模块 __class__
表示当前操作的对象的类是啥么
3. __init__
4. __del__
5. __bases__
显示其父类的集合的元祖
5. __call__
对象后面加括号,促发执行,即对象() 或者 类()()。比较重要
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print '__call__' obj = Foo() # 执行 __init__ obj() # 执行 __call__
6. __dict__
查看类或者对象中的所有成员
class Dog(object): def __init__(self, name): self.name = name def eat(self): print('%s is earting bum ' %(self.name)) d = Dog("Rory") print(Dog.__dict__) # 打印类里的所有属性,不包括实例属性 # 返回:{'__module__': '__main__', '__init__': <function Dog.__init__ at 0x103121840>, 'eat': <function Dog.eat at 0x1031218c8>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None} print(d.__dict__) # 打印所有实例属性,不包括类属性 # 返回:{'name': 'Rory'}
7. __str__
如果一个类中定义了__str__
方法, 那么打印对象时,默认输出该方法的返回值。 不打__str__的话,会返回内存地址。 django中用的比较多。
class Dog(object): def __init__(self, name): self.name = name def eat(self): print('%s is earting bum ' %(self.name)) def __str__(self): return "<obj: %s>" % self.name
8. __getitem__
, __setitem__
, __delitem__
用于索引操作,如字典,以上分别表示获取、设置、删除数据。多数情况用不到。 在封装一个底层的时候,经常会用到,让客户以为在调用一个字典。
class Foo(object): def __init__(self, ): self.data = {} def __getitem__(self, key): print('__getitem__', key) return self.data.get(key) def __setitem__(self, key, value): print("__setitem__", key, value) self.data[key] = value def __delitem__(self, key): print("__delitem__", key) obj = Foo() obj['name'] = 'alex' print(obj.data) del obj["name"]
9. __new__
和 __metaclass__
先来看段代码, 一般我们普通方式创建类如下:
class Foo(object): def __init__(self,name): self.name = name f = Foo("moo") print(type(f)) # 表示:obj对象由Foo类创建得来, f是Foo的一个实例 # 返回:<class '__main__.Foo'> print(type(Foo)) # 表示:Foo类由type类创建得来,Foo是type的一个实例 # 返回:<class 'type'>
这里就引出了第2种创建类的方法,乃装逼利器,即特殊方式。其基本原理(以以上例子为列), f是Foo类创建的,是Foo的一个实例。在python中,一切皆对象。其实Foo类本身也是一个实例,是type类所创建的一个实例。 特殊方式创建类的方式如下:
def func(self): print('hello, 特殊方法') def __init__(self, name, age): self.name = name self.age = age Moo = type("Moo", (object,), {'talk': func, '__init__': __init__}) # type第一参数:类名 # type第二参数:当前类的基类 # type第三参数:类的成员 m = Moo("alex", "22") m.talk()
多数情况不大用到,重点是内部逻辑,以及“一切皆对象”的概念。
类的创建过程(很难理解)
类中有个属性__metaclass__
, 表示该类是由谁来实例化创建的。
与__init__
相比,__new__
更像一个正真的构造器。因为__new__()
必须返回一个合法的实例,这样调用__init__()
时,就可以把这个实例作为self传给它。__init__()
更像解释器创建一个实例后调用的第一个方法。
10. 其他
详见《python核心编程v2》平67-369
类、实例和其他对象的内建函数
1. issubclass(sub, sup)
布尔函数判断一个类是另外一个类的子类或者孙类。 从2.2开始,sup可能是一个父类的集合的元祖。
2. isinstance(obj1, obj2)
布尔函数判断一个对象是否是另外一个给定类的实例,非常有用。 obj2 是给定类。
3. *attr系列函数 hasattr(), getattr(), setattr(),delattr()
重要,详见4.反射
4. dir(obj=None)
dir()
作用在不通对象,内容不同
- 实例:显示实例变量,实例所在的类及所有它的基类中定义的方法及类属性
- 类:显示类以及他的所有基类的
__dict__
的内容。 但它不显示定义在元类metaclass
中的类属性 - 模块:显示模块的
__dict__
的内容 - 不带参数:显示调用者的局部变量
5. super(type, obj=None)
方便的找到所有的父类(不需要给出父类的名称),并调用其相关属性。 而不是一个个采用非绑定方式调用父类方法。
6. var(obj=None)
var()
和dir()
类似。区别在于给定参数必须有一个__dict__
属性。 如果返回不了一个key和value的形式,会出现TypeError异常。