用户:Xyy23330121/Python/类
使用 class
语句,我们可以定义一个类。
class ClassName: pass
这就定义了一个名为 ClassName
的类。与函数相似,“类”自身也是一个对象,支持一切一般对象的操作。
类的属性可以理解为是定义在类中的、特殊的变量。
定义了“类”之后,我们可以在class
子句给类添加属性。也可以在定义后再添加属性,比如:
class MyClass:
attr1 = 1
attr2 = "Two"
print(MyClass.attr1) #调用了 MyClass 的属性 attr1。输出:1
print(MyClass.attr2) #调用了 MyClass 的属性 attr2。输出:Two
MyClass.attr3 = "Third"
print(MyClass.attr3) #调用了 MyClass 的属性 attr3。输出:Third
如上述例子所述。我们可以通过 ClassName.AttrName
的方式调用类的属性。其中 ClassName
指的是类的名称,AttrName
指的是属性的名称
类似,我们可以在类中定义函数。类中的函数和其它函数在表现上毫无区别,只是在使用时需要在前面添加类的名称罢了。
实例是类的一个重要组成部分。比如 1
是类型 int
的一个实例对象。我们创建的类型也可以有实例。
我们可以用 ClassName()
的方法创建实例。
class MyClass1:
a = 0
def Method1(self):
print(self.a, "调用了方法")
a = MyClass1()
print(a.a) #输出:0
a.Method1() #输出:0 调用了方法
如果在类中定义了一个特殊的方法 __init__
我们就可以更灵活地创建实例。我们看以下示例:
class MyClass2:
def __init__(self, arg):
self.arg = arg
a = MyClass3("实例属性")
print(a.arg) #输出:实例属性
在调用 MyClass2()
的时候,我们创建了一个实例,然后把传入 MyClass2()
的参数传入到实例的 __init__
方法中。这个实例是 MyClass2
的实例,它在初始化时具有属性 arg = "实例属性"
。
在类中定义的属性或方法,在实例中也可以使用。我们看以下示例:
class attr:
n = 0
number = 0
array = []
def __init__(self,arg):
number = 1
array.append(arg)
a = attr("First")
b = attr("Second")
print(attr.n, attr.number, attr.array) #输出:0 0 ['First', 'Second']
print(a.n, a.number, a.array) #输出:0 1 ['First', 'Second']
print(b.n, b.number, b.array) #输出:0 1 ['First', 'Second']
可以看出,实例和函数类似。如果在实例中对可变对象的属性作“直接赋值以外的更改操作”,则更改操作会影响到类的属性。但对不可变对象的属性,唯一的更改方式是赋值。此时,该属性在实例作用域里,而非类作用域里。
在类中定义的函数,在实例中也可以使用。此时称该函数是一个“方法”。类中的函数在使用时和其它函数没有区别,但是实例的方法不同。在调用实例的方法时,自动传入的第一个参数的会是实例自身。比如:
class attr:
n = 0
number = 0
array = []
def __init__(self,arg):
number = 1
array.append(arg)
def prt(s):
print(s.n, s.number, s.array)
a = attr("First")
b = attr("Second")
attr.prt() #输出:0 0 ['First', 'Second']
a.prt() #输出:0 1 ['First', 'Second']
b.prt() #输出:0 1 ['First', 'Second']
可以看出,它正确传入了实例,并在可能的条件下使用了实例的属性。而没有使用类的属性。
我们在之前学习函数时,学习过装饰器相关的知识。到了本章节,有两个好用的装饰器可以使用。
该装饰器用于类方法。与一般的方法传入的是实例本身不同,类方法自动传入的第一个参数是实例所属的“类”。我们可以从以下示例中看出这一点:
class C:
isCls = True
def __init__(self):
self.isCls = False
def f(s):
print(s.isCls)
@classmethod
def g(s):
print(s.isCls)
a = C()
a.f() #输出:False
a.g() #输出:True
如同在装饰器中提到的一样,以上类等同于:
class C:
isCls = True
def __init__(self): self.isCls = False
def f(s): print(s.isCls)
g = classmethod(lambda s: print(s.isCls))
该装饰器用于静态方法。静态方法不会受类或实例改动的影响,它和函数的表现完全一致。
class C:
@staticmethod
def f(arg1, arg2):
print(arg1, arg2)
a = C()
a.f(0,1) #输出:0 1
C.f(0,1) #输出:0 1
可以看出,此时使用的方法“不会”自动传入实例自身。这是因为调用装饰器后,装饰器返回的结果,会跳过自动传入的第一个参数,从第二个参数开始处理。
同样,以上的类等同于:
class C:
f = staticmethod(lambda x,y: print(x,y))
类似函数注释。对于类,或实例的方法,我们也可以使用文档字符串。
class ClassWithDoc:
'''文档字符串'''
def MethodWithDoc():
'''文档字符串'''
pass
print(ClassWithDoc.__doc__)
a = ClassWithDoc()
print(a.MethodWithDoc.__doc__)
在类中定义函数时,也可以使用类型注释。