关于类(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.i
和 Myclass.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)的一部分基础内容,后续会另开篇幅继续介绍类的其余相关内容。
欢迎关注微信公众号《书所集录》