最近更新: 2020-9-21
类定义
1 2 3 4
| class ClassName: <statement-1> . <statement-N>
|
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
类对象
类对象支持两种操作:属性引用和实例化。
属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name。
类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class MyClass: """一个简单的类实例""" i = 12345 def f(self): return 'hello world'
x = MyClass()
print("MyClass 类的属性 i 为:", x.i) print("MyClass 类的方法 f 输出为:", x.f())
|
执行以上程序输出结果为:
1 2
| MyClass 类的属性 i 为: 12345 MyClass 类的方法 f 输出为: hello world
|
类有一个名为 init() 的特殊方法(构造方法),该方法在类实例化时会自动调用,像下面这样:
1 2
| def __init__(self): self.data = []
|
类定义了 init() 方法,类的实例化操作会自动调用 init() 方法。如下实例化类 MyClass,对应的 init() 方法就会被调用:
当然, init() 方法可以有参数,参数通过 init() 传递到类的实例化操作上。例如:
1 2 3 4 5 6 7 8
| class Complex: def __init__(self, realpart, imagpart): self.r = realpart self.i = imagpart x = Complex(3.0, -4.5) print(x.r, x.i)
|
self代表类的实例,而非类
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
1 2 3 4 5
| class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt()
|
以上实例执行结果为:
1 2
| <__main__.Test instance at 0x100771878> __main__.Test
|
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。
self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
1 2 3 4 5 6 7
| class Test: def prt(runoob): print(runoob) print(runoob.__class__) t = Test() t.prt()
|
self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
class Test: def prt(runoob): print(runoob) print(runoob.class) t = Test() t.prt()
以上实例执行结果为:
1 2
| <__main__.Test instance at 0x100771878> __main__.Test
|
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
实例(Python 3.0+)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
class people: name = '' age = 0 __weight = 0 def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 说: 我 %d 岁。" %(self.name,self.age))
p = people('runoob',10,30) p.speak()
|
执行以上程序输出结果为:
继承
Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义。派生类的定义如下所示:
1 2 3 4 5 6
| class DerivedClassName(BaseClassName1): <statement-1> . . . <statement-N>
|
BaseClassName(示例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:
1
| class DerivedClassName(modname.BaseClassName):
|
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
|
class people: name = '' age = 0 __weight = 0 def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 说: 我 %d 岁。" %(self.name,self.age))
class student(people): grade = '' def __init__(self,n,a,w,g): people.__init__(self,n,a,w) self.grade = g def speak(self): print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade)) s = student('ken',10,60,3) s.speak()
|
执行以上程序输出结果为:
多继承
Python同样有限的支持多继承形式。多继承的类定义形如下例:
1 2 3 4 5 6
| class DerivedClassName(Base1, Base2, Base3): <statement-1> . . . <statement-N>
|
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,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
|
class people: name = '' age = 0 __weight = 0 def __init__(self,n,a,w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 说: 我 %d 岁。" %(self.name,self.age))
class student(people): grade = '' def __init__(self,n,a,w,g): people.__init__(self,n,a,w) self.grade = g def speak(self): print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
class speaker(): topic = '' name = '' def __init__(self,n,t): self.name = n self.topic = t def speak(self): print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
class sample(speaker,student): a ='' def __init__(self,n,a,w,g,t): student.__init__(self,n,a,w,g) speaker.__init__(self,n,t) test = sample("Tim",25,80,4,"Python") test.speak()
|
执行以上程序输出结果为:
1
| 我叫 Tim,我是一个演说家,我演讲的主题是 Python
|
方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Parent: def myMethod(self): print ('调用父类方法') class Child(Parent): def myMethod(self): print ('调用子类方法') c = Child() c.myMethod() super(Child,c).myMethod()
|
super() 函数是用于调用父类(超类)的一个方法。
执行以上程序输出结果为:
类属性与方法
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。
实例
类的私有属性实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class JustCounter: __secretCount = 0 publicCount = 0 def count(self): self.__secretCount += 1 self.publicCount += 1 print (self.__secretCount) counter = JustCounter() counter.count() counter.count() print (counter.publicCount) print (counter.__secretCount)
|
执行以上程序输出结果为:
1 2 3 4 5 6 7
| 1 2 2 Traceback (most recent call last): File "test.py", line 16, in <module> print (counter.__secretCount) AttributeError: 'JustCounter' object has no attribute '__secretCount'
|
类的私有方法实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Site: def __init__(self, name, url): self.name = name self.__url = url def who(self): print('name : ', self.name) print('url : ', self.__url) def __foo(self): print('这是私有方法') def foo(self): print('这是公共方法') self.__foo() x = Site('菜鸟教程', 'www.runoob.com') x.who() x.foo() x.__foo()
|
以上实例执行结果:
类的专有方法:
- init : 构造函数,在生成对象时调用
- del : 析构函数,释放对象时使用
- repr : 打印,转换
- setitem : 按照索引赋值
- getitem: 按照索引获取值
- len: 获得长度
- cmp: 比较运算
- call: 函数调用
- add: 加运算
- sub: 减运算
- mul: 乘运算
- truediv: 除运算
- mod: 求余运算
- pow: 乘方
运算符重载
Python同样支持运算符重载,我们可以对类的专有方法进行重载,实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print (v1 + v2)
|
$$ —- \mathcal{End} —- $$