Python

Python 知识量:10 - 41 - 150

10.2 使用对象><

初始化- 10.2.1 -

在创建Person对象时,除了使用句点表示法直接对属性赋值外,最好的初始化方法是通过构造函数__init__(self)来完成:

# person.py
class Person:
    def __init__(self,name='',age=0):
        self.name=name
        self.age=age
    def __str__(self):
        return "This is person('%s',%s)." % (self.name,self.age)
    def __repr__(self):
        return str(self)

运行结果为:

>>> 
===================== RESTART: D:/PythonTestFile/person.py =====================
>>> p=Person('Jeff',37)
>>> p
This is person('Jeff',37).

比起逐项对name和age赋值,这样初始化对象的效率就提高了许多。

设置和获取函数- 10.2.2 -

通过句点表示法可以灵活的设置和获取对象属性的值,但是无法避免设置不合理的值,例如将age设为负数。

在Python对象中,可以通过设置函数和获取函数对赋值和取值过程进行管理,下面是示例:

# person.py
class Person:
    def __init__(self,name='',age=0):
        self.name=name
        self.age=age
    def __str__(self):
        return "This is person('%s',%s)." % (self.name,self.age)
    def __repr__(self):
        return str(self)
    def setter_age(self,age):  #设置函数
        if 0<age<100:
            self.age=age
    def getter_age(self):  #获取函数
        return self.age

运行结果为:

>>> 
===================== RESTART: D:/PythonTestFile/person.py =====================
>>> p=Person('Jeff',37)
>>> p
This is person('Jeff',37).
>>> p.setter_age(40)
>>> p
This is person('Jeff',40).
>>> p.setter_age(-18)
>>> p
This is person('Jeff',40).
>>> p.getter_age()
40

装饰器- 10.2.3 -

设置函数为对象属性的赋值提供了必要的管理,但是使用起来又不如直接赋值简便。Python装饰器可以兼容这两个优点:既可以管理输入,又使用简便。下面通过@property和@*.setter这两个装饰器来实现这项任务。

# person.py
class Person:
    def __init__(self,name='',age=0):
        self._name=name  #重命名对象数据为_name
        self._age=age    #重命名对象数据为_age
    def __str__(self):
        return "This is person('%s',%s)." % (self._name,self._age)
    def __repr__(self):
        return str(self)
    @property  #调用装饰器
    def age(self):  #获取函数
        return self._age
    @age.setter  #调用装饰器   
    def age(self,age):  #设置函数
        if 0<age<100:
            self._age=age

运行结果为:

>>> 
===================== RESTART: D:/PythonTestFile/person.py =====================
>>> p=Person('Jeff',37)
>>> p
This is person('Jeff',37).
>>> p.age=25
>>> p
This is person('Jeff',25).
>>> p.age=-18
>>> p
This is person('Jeff',25).
>>> p.age
25

下面对以上代码做一下简要说明:

  • 为了像通过句点表示法使用对象属性那样简便,设置函数和获取函数都使用“age”作为函数名。因此,为避免与对象属性age重名,将对象属性重命名为_name和_age。(带下划线的对象属性命名方式是常见做法。)

  • 装饰器以@打头,@property装饰器可以创建只读属性。也就是说,@property装饰器会将其后紧挨着的函数标记为与该函数同名的只读属性,这相当于将函数变为了属性。设置后,可以按照使用属性的方式获取值,但程序实际执行的是函数age(self)里面的代码。

  • @*.setter装饰器可以创建可读属性。但是注意:@*.setter装饰器必须位于@property装饰器后面,且前后两个被修饰的函数的名称必须保持一致,* 即代表函数名称。也就是说,对于以上示例,@age.setter对应前面的函数age(self)。设置后,可以按照使用属性的方式赋值,但程序实际执行的是函数age(self,age)里面的代码。

通过使用装饰器,就可以形式上像使用对象属性那样调用age,而实际上通过执行设置函数和获取函数来实现其必要的管理等功能。

私有属性- 10.2.4 -

对象的普通属性属于公开的属性,这意味着在对象外部可以轻易的通过句点表示法修改它们,但这样就避免不了无意间的错误更改。为了尽可能避免这类情况的发生,可以设置私有属性。方法是在类定义中的属性名称前加两个下划线,例如:

# person.py
class Person:
    def __init__(self,name='',age=0):
        self.__name=name  #私有属性
        self.__age=age    #私有属性
    def __str__(self):
        return "This is person('%s',%s)." % (self.__name,self.__age)
    def __repr__(self):
        return str(self)

这样设置后,可以采用下面的方法访问对象私有属性:

>>> 
===================== RESTART: D:\PythonTestFile\person.py =====================
>>> p=Person('Jeff',37)
>>> p
This is person('Jeff',37).
>>> p._Person__age  #访问私有属性的正确方式
37 
>>> p.__age  #错误方式
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    p.__age
AttributeError: 'Person' object has no attribute '__age'

对于以上示例,要想访问对象的私有属性,需要在属性前加_Person,否则不能直接访问。