Python是面向对象编程语言。面向对象编程中两个最基本的概念就是类和对象。类是一群有着相同属性和函数的一类对象的模板,类实例化后产生对象。在Python中创建一个类和对象是很容易的。
18.1 定义一个类
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾,通常类名首字母大写:
下面是一个类的例子:
class Document:
"""
这是一个文档字符串
"""
# 类变量
WELCOME_STR = 'Welcome! The context for this book is {}.'
# 初始化函数,对创建的对象进行初始化,第一个参数是self,不能有返回值
def __init__(self, title, author, context):
print('init function called')
self.title = title # 成员变量
self.author = author # 成员变量
self.__context = context # 成员变量
# 类函数,常用来实现不同的初始化函数
@classmethod
def create_empty_book(cls, title, author): # 第一参数是cls
print(cls.WELCOME_STR)
return cls(title=title, author=author, context='nothing')
# 成员函数,第一个参数必须是self
def get_context_length(self):
return len(self.__context)
# 静态函数,通常用在类内其他函数中。
@staticmethod
def get_welcome(context):
return Document.WELCOME_STR.format(context)
可以从下面几个方面,认识这个类:
- 类名是Document,对于Python3,所有类默认都是继承自object类。
- 有一个类变量WELCOME_STR,所有实例化的对象公用的这个类变量。可以在内部类或外部类使用Document.WELCOME_STR 访问。类变量定义在类中且在函数体之外。
__init__
是初始化函数,当创建了这个类的实例后就会立即调用该方法对实例进行初始化。self
表示这个类的一个实例,所有的实例方法的第一个参数必须是self
。__init__
是初始化函数,为实例对象self
设置了三个实例属性,分别是title
,author
和__context
。实例属性与类的具体对象相关,每个对象都有自己的属性,不会像类变量被所有对象共享。get_context_length
是类的一个成员方法,它的第一个参数必须是self
。可以访问类变量,调用成员方法通常是通过实例化的对象,当然是用类名调用也是可以的,不过要传递一个对象对象进去。create_empty_book
是类的一个类方法,用@classmethod标识,它的第一个参数必须是cls
。类方法可以访问类变量,通常通过类名调用。get_welcome
是类的静态方法,它被设计用来在类内部其他函数中使用,不过在类外部也可以通过类名和实例对象调用。
18.2 实例化一个类
实例化类在其他编程语言中一般用关键字 new,比如Java语言。但是在 Python 中并没有这个关键字,类的实例化类似调用函数一样,类名加上括号,括号里面是类的属性值。
以下使用类的名称 Document 来实例化,并通过 __init__
方法接收属性。
d=Document("demo", "chunming", "show you class")
上面一条语句其实Python是执行两步:
- 调用
__new__
方法创建实例对象。
上面类并没有__new__
方法呀。一般不用自己定义,Python默认调用该类的直接父类的__new__
方法来构造该类的实例,如果该类的父类也没__new__
方法, 那么将一直按此规矩追溯至object的__new__
方法。Document类的直接父类是object,所以Document类实例化时,是调用的object类的__new__
方法。看下object的__new__
方法是如何定义的:
@staticmethod # known case of __new__
def __new__(cls, *more): # known special case of object.__new__
""" Create and return a new object. See help(type) for accurate signature. """
pass
可见object的__new__
方法,是一个静态方法,通常使用方式是object.__new__。
- 紧接着用
__init__
方法对对象进行初始化。如果没定义,则不会进行特别的初始化动作。
18.3 访问属性和方法
实例化类之后,就可以用对象访问类变量、实例属性、类方法、实例方法和静态方法了。
在上面的类代码文件中,写下如下测试代码:
if __name__ == '__main__':
d = Document("demo", "chunming", "show you class")
print("访问类变量=", d.WELCOME_STR) # 1.实例对象访问类变量
d0 = d.create_empty_book("有默认content", "实例对象") # 2.实例对象调用类方法
print(d.get_welcome("实例对象调用静态函数")) # 3. 实例对象调用静态方法
print(d.get_context_length()) # 4. 实例对象调用成员方法
print(Document.WELCOME_STR) # 5. 类名访问类变量
# print(Document.title) # 不可以。
print(Document.get_context_length(d)) # 6. 类名访问成员方法
f = Document.create_empty_book("static", "liu") # 7. 类名访问类方法
print(Document.get_welcome("aa")) # 8. 类名访问静态方法
可以访问类的属性和方法,都是通过点号方式。 实例对象和类都可以访问类变量、类方法、实例方法和静态方法。但是类不能访问实例属性。
18.4 如何查看类有哪些属性和方法
有两种办法可以查看类有哪些属性。
- 第一个办法,dir(类名),会显示由属性的名字组成的列表。
['WELCOME_STR', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'create_empty_book', 'get_context_length', 'get_welcome']
- 第二个办法,类名.
__dict__
,是一个字典,包含属性的名字和值
{'__module__': '__main__', '__doc__': '\n 这是一个文档字符串\n ', 'WELCOME_STR': 'Welcome! The context for this book is {}.', '__init__': <function Document.__init__ at 0x1101f9f80>, 'create_empty_book': <classmethod object at 0x110260750>, 'get_context_length': <function Document.get_context_length at 0x11025d710>, 'get_welcome': <staticmethod object at 0x110260790>, '__dict__': <attribute '__dict__' of 'Document' objects>, '__weakref__': <attribute '__weakref__' of 'Document' objects>}
从dir函数和__dict__
的输出可以看出,有些属性我们在Document类中并没有定义,比如__module__
、__class__
、__dict__
以及__doc__
等,这些属性是Python为每一个类自动设定的。
C.__name__
,表示类C的名字C.__dict__
,表示类C的属性以及值。C.__module__
,表示类C的定义所在的模块名称,独立运行模块时为字符串__main__
。模块被导入时,被设置为模块的名称。i.__class__
,表示实例i所属的类C.__bases__
,表示类C的所有直接父类组成的元组,不包括父类的父类C.__doc__
,表示类C的文档字符串。
18.5 类中的方法
- 构造方法
__init__
表示构造函数,对生成的对象进行初始化操作,一个对象生成后会被自动调用的函数。
- 成员方法
- 对象的某个动态能力,比如上述代码中的get_context_length函数,函数的第一个参数是self。
- 静态方法
- 在函数前一行加上
@staticmethod
表示 - 静态方法则与类没有什么关联,用来单独完成些任务,可以在多个成员方法中使用。
- 类方法
- 第一个参数一般为 cls,表示必须传一个类进来。需要装饰器
@classmethod
来声明。 - 常用的场景是实现不同的
__init__
构造函数,比如上文代码中,我们使用 create_empty_book 类函数,来创造新的书籍对象,用它来创造的书籍其 context 一定为 ‘nothing’。
好了。Python类与对象入门就介绍到这里。下一小节我们继续对属性进行输入介绍。