Python基础-类的特殊方法

主要介绍一些内置的特殊方法和重载这些方法


常见的特殊方法
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
"""
常见的一些特殊方法
"""

'''
1.__repr__()方法
当打印实例时 返回的是__repr__()方法的返回值 类似<__main__.Item object at 0x000001D9B89D4508>
重写该方法自定义返回信息
2.__dir__() 放回对象的属性和方法
dir(obj) 返回__dir__()排序后的列表
3.__dict__属性 返回对象的属性 可以访问和修改属性值
4.__del__() 销毁对象方法 当对象还有变量引用时不会回收
'''


class Item:
def __init__(self, name, price):
self.name = name
self.price = price

def __repr__(self):
return "Item:[price:" + str(self.price) + ",name:" + self.name + "]"

def __del__(self):
print("销毁Item对象")


it = Item("书包", 20)
print(it)

print(it.__dir__())
print(dir(it))

print(it.__dict__)
print(it.__dict__['name'])
print(it.__dict__['price'])
it.__dict__['name'] = "手表"
print(it.name)
x = it
del it # 注释掉上面一行会立刻回收对象
print("--------")

'''
1.__getattribute__() 获取属性调用
2.__getattr__() 获取不存在的属性时调用
3.__setattr__() 设置属性时调用
4.——delattr__()删除属性时调用
'''


class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def __setattr__(self, key, value):
print("---设置属性%s---" % key)
if key == 'size':
self.width, self.height = value
else:
self.__dict__[key] = value

def __getattr__(self, item):
print("----读取属性%s----" % item)
if item == 'size':
return self.width, self.height
else:
raise AttributeError # 不存在的属性情况

def __delattr__(self, item):
print("----删除属性%s-----" % item)
if item == 'size':
self.__dict__['width'] = 0
self.__dict__['height'] = 0


re = Rectangle(20, 15)
print(re.size)
re.size = 30, 40
print(re.size)
print(re.width)
del re.size
print(re.size)
动态判断
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
"""
动态判断是否包含属性或者设置值
hasattr(obj,name) 是否有name属性或方法
getattr(obj,name) 获取name属性值
setattr(obj,name,value,..) 设置name属性为value
属性不存在时会添加属性 可设置方法 可把方法改变成属性
"""


class Comment:
def __init__(self, detail, views):
self.detail = detail
self.views = views

def info(self):
print("comment info:%s" % self.detail)


c = Comment("这个真好啊!", 66)
print("hasattr('detail'):", hasattr(c, 'detail'))
print("hasattr('info'):", hasattr(c, 'info'))
print("hasattr('hello'):", hasattr(c, 'hello'))
print("detail:", getattr(c, 'detail'))
print("views:", getattr(c, 'views'))
setattr(c, 'detail', '今天天气不错')
print(c.detail)


def bar():
print("this is method bar")


c.info()
setattr(c, 'info', bar)
c.info()
setattr(c, 'info', 'info message')
print(c.info)
'''
通过__call__属性判断是否可调用
方法的执行就是调用.__call__()方法 可以在类中定义是的类的实例能够执行
'''


class User:
def __init__(self, name):
self.name = name

def info(self):
print("use name is :", self.name)

def __call__(self, *args, **kwargs):
print("user __call__ method")


u = User('lily')
print("hasattr(u.name, '__call__'):", hasattr(u.name, '__call__'))
print("hasattr(u.info, '__call__'):", hasattr(u.info, '__call__'))
u() # 执行User 实例

'''
函数调用__call__()
'''
bar()
bar.__call__() # 和上面效果一样
序列相关方法
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
"""
序列相关方法
__len__() 序列个数
__getitem__() 获取元素
__contains__() 是否包含元素
__setitem__() 设置元素
__delitem__() 删除元素
"""
# 。。。
"""
实现迭代器
实现__iter__() 返回迭代器 迭代器需包含__next__()方法
实现__reversed__ 反转 可以不实现
"""


# 斐波那契数列迭代器
class Fibs:
def __init__(self, length):
self.first = 0
self.sec = 1
self.__len = length

def __next__(self):
if self.__len == 0:
raise StopIteration
self.first, self.sec = self.sec, self.first + self.sec
self.__len -= 1
return self.first

def __iter__(self):
return self


f = Fibs(10)
# print(next(f))
for el in f:
print(el, end=" ")
print("")
# 程序内置iter() 函数能将列表、元组等转换成迭代器
it = iter(['132', 'ra'])
print(it.__next__())
print(it.__next__())
"""
如果需要特殊的字典、列表、元组 可以继承后自行扩展
"""
"""
创建生成器 yield语句函数
yield 返回值 并冻结执行
函数不立刻执行 使用next()函数才会执行
"""


def test(val, step):
print("开始test生成器函数")
cur = 0
for i in range(val):
cur += step
yield cur


t = test(10, 2)
print("----------------")
print(next(t))
print(next(t))
for e in t:
print(e, end=" ")
print(" ")
# (for 循环)语句创建生成器
a_range = range(10)
c_generator = (x * x for x in a_range if x % 2 == 0)
print(next(c_generator))
print(next(c_generator))
运算符相关方法
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
"""
python 可以在类中重载运算符相关方法
使得实例之间能够运算
__add__()....等方法
"""


class Pictures:
def __init__(self, num):
self.num = num

def __add__(self, other):
if not isinstance(other, Pictures):
raise TypeError("type must is Pictures")
else:
return Pictures(self.num + other.num)

def __repr__(self):
return str(self.num)


p1 = Pictures(3)
p2 = Pictures(2)
p3 = p1 + p2
print(p3)

"""
比较运算符也有相关方法
__lt__() 表示 < 、 __le__() 表示 <=
__eq__() 表示 == 、 __ne__() 表示!=
__gt__() 表示 > __ge__() 表示>=
类实现gt eq ge 就可以使用上面的运算符了

单目运算
__neg__() 求负-
__pos__() 求+
__invert__() 取反~

类型转换str() int() float()..等也有对应的特殊方法
__str__()
__int__()...

内建函数的特殊函数
__format__()
__hash__()
__round__()...等
"""


class Name:
def __init__(self, name):
self.name = name

def __gt__(self, other):
return len(self.name) > len(other.name)

def __eq__(self, other):
return len(self.name) == len(other.name)

def __ge__(self, other):
return len(self.name) >= len(other.name)

# 重载单目- 运算 name反转
def __neg__(self):
self.name = self.name[::-1]

# 对象能够传入int()方法
def __int__(self):
return len(self.name)

def __format__(self, format_spec):
return format_spec.join(list(self.name))


n1 = Name('haha')
n2 = Name('ha')
print(n1 > n2)
print(n1 < n2)
print(n1 == n2)
print(n1 >= n2)
print(n1 <= n2)
n3 = Name("这个是反转")
-n3
print(n3.name)
print(int(n3))
r = format(n3, '%')
print(r)