简介
class是面向对象编程的一个非常重要的概念,python中也有class,并且支持面向对象编程的所有标准特性:继承,多态等。
本文将会详细讲解Python中class的信息。
作用域和命名空间
在详细讲解class之前,我们来看一下作用域和命名空间的概念。
命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
命名空间主要是为了避免程序中的名字冲突。只要名字在同一个命名空间中保持唯一即可,不同的命令空间中的名字互不影响。
Python中有三种命名空间:
- 内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
- 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
- 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)
命名空间的搜索顺序是 局部名称-》全局名称-》内置名称。
在不同时刻创建的命名空间拥有不同的生存期。包含内置名称的命名空间是在 Python 解释器启动时创建的,永远不会被删除。模块的全局命名空间是在在模块定义被读入时创建.
通常,模块命名空间也会持续到解释器退出。
被解释器的顶层调用执行的语句,比如从一个脚本文件读取的程序或交互式地读取的程序,被认为是 main 模块调用的一部分,因此它们也拥有自己的全局命名空间。(内置名称实际上也存在于一个模块中;这个模块称作 builtins 。)
一个 作用域 是一个命名空间可直接访问的 Python 程序的文本区域。
Python中有四种作用域:
- Local:最内层,包含局部变量,比如一个函数/方法内部。
- Enclosing:包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
- Global:当前脚本的最外层,比如当前模块的全局变量。
- Built-in: 包含了内建的变量/关键字等。,最后被搜索
作用域的搜索顺序是 Local -> Enclosing -> Global -> Built-in
Python中用nonlocal关键字声明为Enclosing范围,用global关键字声明为全局范围。
我们来看一个global 和 nonlocal 会如何影响变量绑定的例子:
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
def do_global():
global spam
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
上面程序输出:
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam
函数内的变量默认是local作用域,如果要在函数的函数中修改外部函数的变量,那么需要将这个变量声明为nonlocal, 最后在模块顶层或者程序文件顶层的变量是全局作用域,如果需要引用修改的话需要声明为global作用域。
class
Python中的类是用class来定义的,我们看一个最简单的class定义:
class ClassName:
<statement-1>
.
.
.
<statement-N>
类定义中的代码将创建一个新的命名空间,里面的变量都被看做是局部作用域。所有对局部变量的赋值都是在这个新命名空间之内。
类对象
class定义类之后,就会生成一个类对象。我们可以通过这个类对象来访问类中定义的属性和方法。
比如我们定义了下面的类:
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
类中定义了一个属性 i 和一个方法 f。那么我们可以通过 MyClass.i和MyClass.f 来访问他们。
注意,Python中没有像java中的private,public这一种变量访问范围控制。你可以把Python
class中的变量和方法都看做是public的。
我们可以直接通过给 MyClass.i 赋值来改变 i 变量的值。
In [2]: MyClass.__doc__
Out[2]: 'A simple example class'
In [3]: MyClass.i=100
In [4]: MyClass
Out[4]: __main__.MyClass
In [5]: MyClass.i
Out[5]: 100
Class中,我们还定义了class的文档,可以直接通过 doc 来访问。
类的实例
实例化一个类对象,可以将类看做是无参的函数即可。
In [6]: x = MyClass()
In [7]: x.i
Out[7]: 100
上面我们创建了一个MyClass的实例&#x