Python方法

方法

属性方法

概念

属性方法即使用@property装饰器,将函数中的方法转化为”属性”,即可以直接使用访问属性的方式,即属性名.方法进行方法的调用。

内置函数property@property

  • property函数
    property函数的作用是托管类的属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class C:
def __init__(self):
self._x = 'This is x'

def getx(self):
return self._x

def setx(self, value):
self._x = value

def delx(self):
del self._x

x = property(getx, setx, delx, "I'm the 'x' property.")

c = C()

print(c.x) # 调用getter
c.x = 'value' # 调用setter
del c.x # 调用deleter
  • @property装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 下面类与上述例子具有相同的效果
class C:
def __init__(self):
self._x = None

@property
def x(self):
"""I'm the 'x' property."""
return self._x

@x.setter
def x(self, value):
self._x = value

@x.deleter
def x(self):
del self._x
c = C()

print(c.x) # 调用getter
c.x = 'value' # 调用setter
del c.x # 调用deleter

类方法(@classmethod)

概念

类方法的调用可以在类上进行也可以在实例上进行。
@classmethod装饰器将一个方法封装成类方法。

意义

  • python中的类方法解决了python中不可以通过不同的参数来重载不同的构造函数的问题。即python可以通过类方法实现在实例化前进行某些操作,进而实现类似于多个构造函数的效果。
  • 对于某些需要在类实例化之前做些交互操作提供实现方法。
  • 在继承的时,保证了子类使用可选构造函数构造出来的类是子类的实例而不是父类的实例。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo(object):

def bar_1(self):
print ('this is bar_1')

@classmethod
def bar_2(cls):
print ('this is bar_2')
cls().bar_1()

Foo.bar_2()

# 输出
this is bar_2
this is bar_1

静态方法

概念

静态方法的调用可以在类上进行也可以在实例上进行。

意义

静态方法其本质是函数,虽然静态方法定义在类中,但是静态方法并不是类或者类实例的方法,而可以理解为与类没有直接关系的函数,那么静态方法定义在类中的意义是因为可以将一些功能性的工具函数放在类中,方便调用。

示例

1
2
3
4
5
6
7
8
9
10
class Foo(object):

def bar_1(self):
print ('this is bar_1')

@staticmethod
def bar_2():
print ('this is bar_2')

Foo.bar_2()

特殊成员方法(魔术方法)

常用魔术方法

__new__(cls[, …])
python3中在类实例化过程中首先要调用__new__(cls[, …])方法,其第一个参数是当前类,其余参数在随后的过程中传递至__init__方法。

__init__(self[, …])
可以理解为python中的构造方法,当一个实例被创建时进行初始化的方法。

__del__(self)
python中的析构方法,当实例被销毁时调用该方法,可以执行清理相关功能。

__call__(self[, args…])
允许一个类的实例像函数一样被调用:foo(x, y) 调用 foo.__ call__(x, y)

__len__(self)
调用len() 时的操作

__repr__(self)
调用repr() 时的操作

__str__(self)
调用str() 时的操作

__bytes__(self)
调用bytes() 时的操作

__hash__(self)
调用hash() 时的操作

__bool__(self)
调用bool() 时的操作,返回True或False

__format__(self, format_spec)
调用format() 时的操作

属性相关

__getattr__(self, name)
当尝试获取不存在的属性时的操作

__getattribute__(self, name)
当前类的属性被访问时的操作

__setattr__(self, name, value)
定义当一个属性被设置时的行为

__delattr__(self, name)
当属性被删除时的操作

__dir__(self)
调用dir()时的操作

__get__(self, instance, owner)
当获得描述符的值时的操作

__set__(self, instance, value)
当修改描述符的值时的操作

__delete__(self, instance)
当删除描述符的值时的操作

比较操作符

__lt__(self, other)
调用小于号时的操作:即x < y 调用 x.lt(y)
__le__(self, other)
调用小于等于号时的操作:即x <= y 调用 x.le(y)
__eq__(self, other)
调用等于号时的操作:即x == y 调用 x.eq(y)
__ne__(self, other)
调用不等于号时的操作:即x != y 调用 x.ne(y)
__gt__(self, other)
调用大于号时的操作:即x > y 调用 x.gt(y)
__ge__(self, other)
调用大于等于号时的操作:即x >= y 调用 x.ge(y)

算数运算符 & 反运算

反运算:即当左操作数不存在对应方法时,则检查右操作数是否有相对应的反运算符,若有则进行对应运算,若没有则抛出异常

__radd/add__(self, other)
调用加法时的操作:+

__rsub/sub__(self, other)
调用减法时的操作:-

__rmul/mul__(self, other)
调用乘法时的操作:*

__rtruediv/truediv__(self, other)
调用除法时的操作:/

__rfloordiv/floordiv__(self, other)
调用整除时的操作://

__rmod/mod__(self, other)
调用取模运算时的操作:%

__rdivmod/divmod__(self, other)
调用 divmod() 时的操作

__rpow/pow__(self, other[, modulo])
调用 power() 或 ** 时的操作

__rlshift/lshift__(self, other)
调用按位左移时的操作:<<

__rrshift/rshift__(self, other)
调用按位右移时的操作:>>

__rand/and__(self, other)
调用按位与时的操作:&

__rxor/xor__(self, other)
调用按位异或时的操作:^

__ror/or__(self, other)
调用按位或时的操作:|

增量赋值运算

上述算数运算符前增加i,则转换为对应的增量赋值运算符,对应操作转换为赋值运算
例如:__iadd__(self, other),则调用赋值加法时的操作,即+=

一元操作符

__pos__(self)
调用正号时的操作

__neg__(self)
调用负号时的操作

__abs__(self)
调用 abs() 时的操作

__invert__(self)
调用按位求反时的操作

类型转化

__complex__(self)
调用 complex() 时的操作

__int__(self)
调用 int() 时的操作

__float__(self)
调用 float() 时的操作

__round__(self[, n])
调用 round() 时的操作

__index__(self)
调用此方法以实现 operator.index() 以及 Python 需要无损地将数字对象转换为整数对象的场合(例如切片或是内置的 bin(), hex() 和 oct() 函数)。存在此方法表明数字对象属于整数类型。必须返回一个整数。

上下文管理

__enter__(self)
当使用 with 语句时,返回值被 with 语句的目标或者 as 后的名字绑定。

__exit__(self, exc_type, exc_value, traceback)
退出关联到此对象的运行时上下文。通常用于处理异常、清除处理或做一些代码块执行完毕之后的日常工作。

容器类型

__len__(self)
调用 len() 时的操作

__getitem__(self, key)
获取容器中元素时的操作: self[key]

__setitem__(self, key, value)
设置容器中元素时的操作: self[key] = value

__delitem__(self, key)
删除容器中元素时的操作: del self[key]

__iter__(self)
对容器中元素进行迭代时的操作

__reversed__(self)
被 reversed() 调用时的操作

__contains__(self, item)
调用 in 时的操作

__slots__

  • 概念
    __slots__ 允许我们显式地声明数据成员并禁止创建 __dict____weakref__ (除非是在 slots 中显式地声明或是在父类中可用。)

  • 意义及作用

  • 相比使用 dict 此方式可以显著地节省空间。

  • 属性查找速度也可得到显著的提升。

  • __slots__不可被继承,也不可动态添加属性

  • 示例

1
2
3
4
5
6
7
8
9
10
11
class Foo:
__slots__ = ['x', 'y']

def __init__(self, x, y):
self.x = x
self.y = y

f = Foo('a', 'b')
print(f.x) # 输出 'a'
print(f.y) # 输出 'b'
f.z = 'new' # 抛出 AttributeError 异常

反射(自省)

概念

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

python中的反射

通过字符串的形式操作对象相关的属性,python中的一切事物都是对象(都可以使用反射)。

反射的实现

  • hasattr(obj, name)
    返回obj对象是否具有name所描述的属性

  • getattr(obj, name)
    从obj对象中获取到name所描述的属性

  • setattr(obj, name, value)
    给obj对象设置一个名为name的属性,属性值为value

  • delattr(obj, name)
    从obj对象中删除名为name的属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#  反射示例中的属性和方法
class Foo:
static_var = '类的静态变量'

def __init__(self, x, y):
self.x = x
self.y = y

def bar(self):
print('this is bar')

foo = Foo('a', 'b')

# 用hasattr函数检测是否含有某属性
print(hasattr(foo, 'x'))
print(hasattr(foo, 'y'))


# 用getattr获取属性
print(getattr(foo, 'x'))

func=getattr(foo, 'y')

func() # 输出'a'

print(getattr(foo, 'm', '不存在')) # 报错


# 用setattr设置属性
setattr(foo, 'z', 'c')
setattr(foo, 'new_attr', lambda self:self.x + '_new_attr')
print(foo.__dict__)
print(foo.bar(foo))

# 用delattr删除属性
delattr(foo, 'x')
delattr(foo, 'y')
delattr(foo, 'not_exist_func') # 不存在,报错

print(foo.__dict__)

# 反射类的方法和属性
class Foo(object):
static_var = "类的静态属性"

def __init__(self):
self.name = '人身苦短'

def func(self):
return '我用python'

@staticmethod
def bar():
return 'bar func...'

print(getattr(Foo, 'static_var'))
print(getattr(Foo, 'func'))
print(getattr(Foo, 'bar'))

# 反射模块的属性和方法(内置模块也是可以的)
'''
程序目录:
module_test.py
index.py

当前文件:
index.py
'''
import module_test as obj

print(hasattr(obj, 'test'))

print(getattr(obj, 'test'))

# 反射自身模块中的函数
import sys

def func_1():
print('funx_1')

def funx_2():
print('funx_2')

this_module = sys.modules[__name__] # 返回自己的模块

print(hasattr(this_module, 'func_1'))
print(getattr(this_module, 'funx_2'))