欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

Python面向对象-特殊成员

发布时间:2025/3/21 52 豆豆
生活随笔 收集整理的这篇文章主要介绍了 Python面向对象-特殊成员 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

我们知道类中有字段、方法和属性三大类成员,并且成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。

Python的类成员还存在着一些具有特殊含义的成员,其中有一些比较重要的,我们一一来看:

(1) __init__

构造方法,通过类创建对象时,自动触发执行。

1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 5 ...

(2) __del__

析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

1 class Student(object): 2 ... 3 4 def __del__(self): 5 pass

(3) __call__

我们已经知道了类名后面加()是调用__init__方法,那对象后面加()呢?请看下面的代码:

1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 5 def __call__(self): 6 print(self.name) 7 8 ... 9 10 mike = Student("Mike") 11 mike()

程序输出是: Mike ,我们可以看到对象()会调用__call__方法,我们可以通过callable()函数判断对象是否可以调用

(4) __dict__

有没有办法获取对象里所有普通字段及其值呢?Python为我们提供了__dict__:

1 class Student(object): 2 Nation = "China" 3 4 def __init__(self, name): 5 self.name = name 6 self.score = 0 7 8 ... 9 10 mike = Student("Mike") 11 print(mike.__dict__)

程序输出: {'score': 0, 'name': 'Mike'} ,对于静态字段Nation = "China",__dict__内并不包含

(5) __str__ , __repr__ 

对于一个对象,我们对其使用print时,默认程序输出的是对象的内存地址:

1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 self.score = 0 5 6 ... 7 8 mike = Student("Mike") 9 print(mike)

程序输出: <__main__.Student object at 0x0050F7B0> 

怎么才能打印得好看呢?只需要定义好__str__()方法,返回一个好看的字符串就可以了:

1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 self.score = 0 5 6 def __str__(self): 7 return self.name 8 ... 9 10 mike = Student("Mike") 11 print(mike)

程序输出就是__str__方法的返回值: Mike 

如果我们把上面的代码在idle里运行,并敲下mike时(>>>mike),打印出来的还是对象的地址,

这是因为直接显示变量调用的不是__str__(),而是__repr__(),两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。

解决办法是再定义一个__repr__()。但是通常__str__()和__repr__()代码都是一样的,所以,有个偷懒的写法:

1 class Student(object): 2 def __init__(self, name): 3 self.name = name 4 self.score = 0 5 6 def __str__(self): 7 return self.name 8 __repr__ = __str__

(6) __iter__

如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

我们以斐波那契数列为例,写一个Fib类,可以作用于for循环:

1 class Fib(object): 2 def __init__(self, maximum): 3 self.a = 0 4 self.b = 1 # 初始化两个计数器a,b 5 self.maximum = maximum # 定义停止循环的条件 6 7 def __iter__(self): 8 return self # 实例本身就是迭代对象,故返回自己 9 10 # Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到 11 # StopIteration错误时退出循环 12 def __next__(self): 13 self.a, self.b = self.b, self.a + self.b 14 if self.a > self.maximum: 15 raise StopIteration() 16 return self.a 17 18 for item in Fab(100): 19 print(item)

(7) __getitem__、__setitem__、__delitem__

上面的Fib类的对象虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,比如,取第4个元素:

1 Fib(100)[4] 2 TypeError: 'Fib' object does not support indexing

要表现得像list那样按照下标取出元素,需要实现__getitem__()方法

1 def __getitem__(self, i): 2 a, b = 0, 1 3 for x in range(i): 4 a, b = b, a + b 5 if a <= self.maximum: 6 return a 7 else: 8 raise ValueError("Out of range")

现在,就可以按下标访问数列的任意一项了: print("Fib(100)[4]:", Fib(100)[4]) ,输出是: Fib(100)[4]: 3 

list还有个神奇的切片方法,Fib该如何实现呢?__getitem__()传入的参数可能是一个int,也可能是一个切片对象slice,所以要做判断:

1 def __getitem__(self, i): 2 if isinstance(i, int): 3 a, b = 0, 1 4 for x in range(i): 5 a, b = b, a + b 6 if a <= self.maximum: 7 return a 8 else: 9 raise ValueError("Out of range") 10 elif isinstance(i, slice): 11 if isinstance(i, slice): # i是切片 12 start = i.start 13 stop = i.stop 14 if start is None: 15 start = 0 16 a, b = 1, 1 17 L = [] 18 for x in range(stop): 19 if x >= start: 20 L.append(a) 21 a, b = b, a + b 22 return L

但是没有对step参数作处理,也没有对负数作处理,所以,要正确实现一个__getitem__()还是有很多工作要做的。

此外,如果把对象看成dict,__getitem__()的参数也可能是一个可以作key的object,例如str。

与之对应的是__setitem__()方法,把对象视作list或dict来对集合赋值。最后,还有一个__delitem__()方法,用于删除某个元素:

1 def __getitem__(self, i): 2 if isinstance(i, int): # 对应于list, tuple的索引 3 a, b = 0, 1 4 for x in range(i): 5 a, b = b, a + b 6 if a <= self.maximum: 7 return a 8 else: 9 raise ValueError("Out of range") 10 elif isinstance(i, slice): # 对应于list,tuple的切片 11 if isinstance(i, slice): # i是切片 12 start = i.start 13 stop = i.stop 14 if start is None: 15 start = 0 16 a, b = 1, 1 17 L = [] 18 for x in range(stop): 19 if x >= start: 20 L.append(a) 21 a, b = b, a + b 22 return L 23 elif isinstance(i, str): # 对应于字典的dic[key]或dic.get[key] 24 print(type(i)) 25 else: 26 print("wrong type") 27 28 def __setitem__(self, key, value): # 对应于字典的dic[key] = value 29 print("key:value", key, value) 30 31 def __delitem__(self, key): # 对应于del dic[key] 32 print("del", key)

 

转载于:https://www.cnblogs.com/z-joshua/p/6398231.html

总结

以上是生活随笔为你收集整理的Python面向对象-特殊成员的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。