Python面向对象编程第03篇 类变量

Posted 不剪发的Tony老师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python面向对象编程第03篇 类变量相关的知识,希望对你有一定的参考价值。

本篇我们学习类变量(类属性)的概念和原理。

类变量简介

Python 中的一切皆对象,包括类。也就是说,Python 类也是一个对象。

当我们使用 class 关键字定义类时,Python 会创建一个对象,对象名称就是该类的名称。例如:

class htmlDocument:
   pass

以上示例定义了 HtmlDocument 类以及 HtmlDocument 对象。HtmlDocument 对象拥有 __name__ 属性:

print(HtmlDocument.__name__)
HtmlDocument

同时,HTMLDocument 的类型为 type:

print(type(HtmlDocument))
<class 'type'>

他是 type 类的一个实例:

print(isinstance(HtmlDocument, type))
True

类变量和类相关联,它们被该类的所有实例共享。以下示例为 HtmlDocument 类增加了两个类变量 extension 和 version:

class HtmlDocument:
    extension = 'html'
    version = '5'

extension 和 version 都是 HtmlDocument 类的变量,它们和 HtmlDocument 类相关联。

获取类变量的值

如果想要获取类变量的值,可以使用点号表示法(.)。例如:

print(HtmlDocument.extension) # html
print(HtmlDocument.version) # 5

如果访问的类变量不存在,Python 将会返回一个 AttributeError 异常。例如:

HtmlDocument.media_type
AttributeError: type object 'HtmlDocument' has no attribute 'media_type'

获取类变量值的另一个方法就是使用 getattr() 函数。该函数接受一个对象和变量名作为参数,返回对应类变量的值。例如:

extension = getattr(HtmlDocument, 'extension')
version = getattr(HtmlDocument, 'version')

print(extension)  # html
print(version)  # 5

如果访问的类变量不存在,同样会返回一个 AttributeError 异常。为了避免这个异常,我们可以为 getattr() 函数指定一个默认的返回值。例如:

media_type = getattr(HtmlDocument, 'media_type', 'text/html')
print(media_type)
text/html

设置类变量的值

如果想要设置类变量的值,同样可以使用点号表示法:

HtmlDocument.version = 10

或者也可以使用内置的 setattr() 函数:

setattr(HtmlDocument, 'version', 10)

Python 是一种动态编程语言,我们可以在运行时为类增加变量。例如,以下示例为 HtmlDocument 类增加了一个类变量 media_type:

HtmlDocument.media_type = 'text/html'
print(HtmlDocument.media_type)

同样,我们也可以使用 setattr() 函数:

setattr(HtmlDocument, media_type, 'text/html')
print(HtmlDocument.media_type)

删除类变量

如果想要在运行时删除类变量,可以使用 delattr() 函数:

delattr(HtmlDocument, 'version')

或者也可以使用 del 关键字:

del HtmlDocument.version

类变量的存储

Python 将类变量存储在 __dict__ 属性中。__dict__ 是一个映射代理,也就是字典。例如:

from pprint import pprint


class HtmlDocument:
    extension = 'html'
    version = '5'


HtmlDocument.media_type = 'text/html'

pprint(HtmlDocument.__dict__)

输出结果如下:

mappingproxy('__dict__': <attribute '__dict__' of 'HtmlDocument' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'HtmlDocument' objects>,
              'extension': 'html',
              'media_type': 'text/html',
              'version': '5')

从输出结果可以看出,除了其他预定义的类变量之外,__dict__ 还包含了三个类变量:extension、media_type 以及 version。

Python 不允许直接修改 __dict__。例如,以下代码返回了一个错误:

HtmlDocument.__dict__['released'] = 2008
TypeError: 'mappingproxy' object does not support item assignment

尽管如此,我们可以使用 setattr() 函数或者点号表示法间接修改 __dict__ 属性。

另外,__dict__ 的键都是字符串,可以帮助 Python 提高变量的查找速度。

虽然 Python 允许通过 __dict__ 字典访问类变量,但是不推荐这样做。而且某些情况下无法通过该字典访问变量,例如:

print(HtmlDocument.__dict__['type']) # BAD CODE

可调用的类属性

类属性可以是任何对象,包括函数。

当我们为类增加一个函数时,函数就成为了一个类属性。由于函数可以被调用,因此这种类属性也被称为可调用的类属性。例如:

from pprint import pprint


class HtmlDocument:
    extension = 'html'
    version = '5'

    def render():
        print('Rendering the Html doc...')


pprint(HtmlDocument.__dict__)

输出结果如下:

mappingproxy('__dict__': <attribute '__dict__' of 'HtmlDocument' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'HtmlDocument' objects>,
              'extension': 'html',
              'render': <function HtmlDocument.render at 0x0000025302446B90>,
              'version': '5')

以上示例中,render 是 HtmlDocument 类的一个类属性,它的值是一个函数。

总结

  • Python 类是一种对象,也是 type 类的一个实例。
  • 类变量是类对象的属性。
  • 使用点号表示法或者 getattr() 函数获取类变量的值。
  • 使用点号表示法或者 setattr() 函数设置类变量的值。
  • Python 是一种动态编程语言,我们可以在运行时增加类变量。
  • Python 类变量存储在 __dict__ 属性中,该属性是一个字典。

以上是关于Python面向对象编程第03篇 类变量的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象编程第09篇 再谈类变量

Python面向对象编程第09篇 再谈类变量

Python面向对象编程第08篇 私有变量

Python面向对象编程第08篇 私有变量

Python面向对象编程第06篇 实例变量

Python面向对象编程第06篇 实例变量