静态方法
截断了类和方法的内在联系。 只是名义上归类管理,实际上在静态方法里访问不了类或者实例中的任何属性。
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异常。