Python 类(Class)

类(Class)


关于类(Class),是一个很抽象的概念。本篇幅简单介绍关于类的一些基础内容。更多深刻的内容,可详阅官方文档:html

https://docs.python.org/3/tutorial/index.htmlpython

在 Python 中,全部的数据类型均可以视为对象,也能够自定义对象。自定义对象数据类型就是类(Class)的概念。编程

Python 的类提供了面向对象编程的全部标准特性:类继承机制容许多个基类,派生类能够覆盖基类的任何方法,一个方法能够调用基类中相同名称的方法。微信

类定义语法


最简单的类定义的语法以下:app

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

类定义,和函数定义相似,必须定义执行后才能生效。函数

类对象


类对象支持两种操做:属性引用和实例化。设计

这里的属性引用使用的是 Python 中全部属性引用的标准语法:obj.name。有效的属性名称是类对象被建立存在于类命名空间的全部名称。假设,类定义以下:code

class MyClass:
    """A simple example class"""
    i = 123
    
    def func(self):
        return "hello world"

在这里 MyClass.iMyclass.func 属于有效属性,分别返回一个整数和一个函数对象。类属性能够被赋值,因此也能够经过赋值改变 MyClass.i 的值。在这里 __doc__ 也是一个有效的属性,它返回的是一个所属类的文档字符串:"A simple example class"htm

类的实例化使用函数表示法。例如,沿用上面的类:对象

x = MyClass()

建立类的实例,并将此对象赋值给变量 x。在这个实例化操做的过程当中,建立的是一个空对象。但许多类喜欢建立带特定初始状态的自定义实例。所以,一个类可以定义一个特殊的方法:__init__(),例如:

def __init__(self):
    self.data = []

若是一个类定义了 __init__() 方法,建立新的实例的时候,会自动调用该方法。

固然,这个方法还可以有额外的参数。在这种状况下,提供给类实例化的参数都会传递给 __init__(),例如:

>>> class Student:
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...
>>> s = Student('demon', 21)

>>> s.name, s.age
('demon', 21)

实例对象


从属性引用来理解实例对象。两种有效的属性名称包括:数据属性和方法。

数据属性不须要声明:它会像局部变量同样,在首次赋值的时候产生。

另外一种实例属性引用称为方法。方法是从属于对象的函数。(方法并不是类实例所特有的,其余对象也有方法。本篇幅若无特别说明,方法一词专指类实例对象的方法)

实例对象的有效方法名称依赖于所属的类。根据定义,一个类全部为对象的属性都定义了与实例的相应方法。

在上面自定义的 MyClass 类中,x.func 是有效的方法引用,由于 MyClass.func 是一个函数,而 x.i 并非方法,由于 MyClass.i 并非一个函数。但 x.func 并非就等同于 MyClass.func,由于 x.func 是一个方法对象,不是函数对象。

方法对象


在上面 MyClass 的例子中,执行下面的语句:

x.func()

这个时候回返回 hello world。可是,当不想立刻就调用方法时,由于 x.func 是一个方法对象,能够将其赋值给一个变量,等待后面调用。

xf = x.func
print(xf())

当执行 print 语句时,一样会返回 hello world

将前面的例子从新放到这里:

class MyClass:
    """A simple example class"""
    i = 123
    
    def func(self):
        return "hello world"

x = MyClass()

在前面执行 x.func() 的时候,这里并无带参数,可是在 func 的函数定义时,指定了一个 self 参数。

这就是方法特殊的地方,实例对象会做为函数的第一个参数被传入。其实调用 x.func 等同于 MyClass.func(x)

类和实例变量


通常来讲,实例变量用于每一个实例的惟一数据,类变量用于类的全部实例共享的属性和方法,以下实例:

class Dog:
    # 类变量,用于全部实例共享
    kind = 'canine'

    def __init__(self, name):
        # 实例变量,每一个实例专有
        self.name = name

>>> d = Dog('Emy')
>>> e = Dog('Buddy')
>>> d.kind
'canine'
>>> e.kind
'canine'
>>> d.name
'Emy'
>>> e.name
'Buddy'

由上面的例子能够看出, kind 类变量是全部实例共有的,而实例变量 name 则是每一个实例独有的。

须要注意的是,共享的数据如果涉及到可变对象,每每获得的结果并非指望的结果。例如:

class Dog:

    tricks = []

    def __init__(self, name):
        self.name = name
    
    def add_tricks(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Emy')
>>> e = Dog('Buddy')
>>> d.add_tricks('roll over')
>>> e.add_tricks('play dead')
>>> d.tricks
['roll over', 'play dead']
>>> e.tricks
['roll over', 'play dead']

在这里能够看出,列表不该该被用做类变量。正确的类设计应该使用实例变量:

class Dog:

    def __init__(self, name):
        self.name = name
        self.tricks = []
    
    def add_tricks(self, trick):
        self.tricks.append(trick)

>>> d = Dog('Emy')
>>> e = Dog('Buddy')
>>> d.add_tricks('roll over')
>>> e.add_tricks('play dead')
>>> d.tricks
['roll over']
>>> e.tricks
['play dead']
注意事项: 数据属性会覆盖具备相同名称的方法属性。如果程序当中的代码量够大,这种状况颇有可能会发生。因此能够作某些约定来最小化这种可能产生冲突的状况。例如在属性名称前加一个下划线,或者方法属性用动词来命名,名词来命名数据属性。

以上就是关于类(Class)的一部分基础内容,后续会另开篇幅继续介绍类的其余相关内容。

欢迎关注微信公众号《书所集录》
相关文章
相关标签/搜索