类的继承与高级特性

之前学Python的时候,感觉Python好简单。最近看图神经网络相关代码,看到了大佬的代码,感觉一万个草泥马在奔腾,原来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
# 在python 3 中已经默认就帮你加载了object了
class A(object):
def __init__(self, name):
self.name = name
"""可以理解为当通过子类的super().__init__方法调用父类初始化函数的时候,子类继承并覆盖了父类的属性:
执行父类构造函数,向子类中添加子类中未定义的属性;对于子类和父类均定义的方法和属性,采用的是子类中方法和属性;
所以执行父类中的方法,若子类已经覆盖,则执行子类中的方法。"""
print('self.run:', self.run) # <bound method B.run of dog()>
self.run()

def run(self):
raise NotImplementedError

# 特殊的__len__()方法,可以保证len()函数可以使用
def __len__(self):
return len(self.name)

#该方法可以让类实现迭代功能,可以使用下标或者for...in方法
def __getitem__(self, idx):
return self.name[idx]

class B(A):
def __init__(self, name):
super(B, self).__init__(name) # 初始化父类

def run(self):
print('name:', self.name) # 继承了父类中的属性

# @property将方法变成属性调用,属性的值为函数返回值
@property
def processed_file_names(self):
result = 'data' + '.pt'
return result

# 重写__repr__,当程序员直接打印该对象时,系统将会输出下面自定义的“自我描述”信息
def __repr__(self):
return '{}()'.format(self.name)

# @staticmethod使得类中的方法不需要实例化解就可以调用
@staticmethod
def fun():
return 'fun'

name = 'dog'
MyB = B(name)

print('MyB:', MyB) # 调用B中的__repr__方法
print('len(MyB):', len(MyB)) # 调用A中的__len__()方法
print('MyB[0]:',MyB[0]) # 调用A中的__getitem__方法
print('MyB.processed_file_names:', MyB.processed_file_names) # 方法变成属性

print('B.fun():', B.fun())

输出结果:

1
2
3
4
5
6
7
self.run: <bound method B.run of dog()>
name: dog
MyB: dog()
len(MyB): 3
MyB[0]: d
MyB.processed_file_names: data.pt
B.fun(): fun

这个代码我感觉注释的还可以,不想再过多解释了。遇到问题看代码就行了。

__class__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
'''类.__class__总是返回<type'type'>;实例.__class__返回实例所属的类的一个引用;实例.__class__()返回一个新的实例'''
class A(object):
pass
>>> A.__class__
<type 'type'>
>>> a=A()
>>> a
<__main__.A object at 0x01B91690>
>>> a.__class__
<class '__main__.A'>
>>> a.__class__() #返回了类的一个新的实例
<__main__.A object at 0x01B915D0>
>>> A.__class__(A) #与A.__class__一样
<type 'type'>

__name__

模块是对象,并且所有的模块都有一个内置属性 __name__。一个模块的 __name__的值取决于您如何应用模块。如果 import 一个模块,那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名。但是您也可以像一个标准的程序样直接运行模块,在这 种情况下, __name__的值将是一个特别缺省”__main__“。

在cmd 中直接运行.py文件,则__name__的值是'__main__';

而在import 一个.py文件后,__name__的值就不是'__main__'了;

从而用if __name__ == '__main__'来判断是否是在直接运行该.py文件

1
2
3
4
5
6
7
8
9
10
11
#Test.py
class Test:
def __init(self):pass
def f(self):print 'Hello, World!'
if __name__ == '__main__':
Test().f()
#End
你在cmd中输入:
C:>Python Test.py
Hello, World!
说明:"__name__ == '__main__'"是成立的

1
2
3
4
5
6
7
8
9
你再在cmd中输入:
C:>python
>>>import Test
>>>Test.__name__ #Test模块的__name__
'Test'
>>>__name__ #当前程序的__name__
'__main__'
无论怎样,Test.py中的"__name__ == '__main__'"都不会成立的!
所以,下一行代码永远不会运行到!

参考

python中的class
每日一发Python—-Python中的name和类

------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道