Python中的属性

8 投票
4 回答
4665 浏览
提问于 2025-04-16 04:31

为什么要使用变量 self._age 呢?这个名字听起来和已经用过的 self.age 没什么关系,为什么不直接用 self.age 呢?

class newprops(object):
    def getage(self):
        return 40
    def setage(self, value):
        self._age = value
    age = property(getage, setage, None, None)

4 个回答

4

你的例子其实没什么意义,因为这个获取器返回的是一个常量。通常情况下,带下划线的变量是和属性一起使用的,属性可以分为:

1) 只读

class C(object):
    @property
    def age(self):
        return self._age

在这种情况下,instance.age 只能读取,不能赋值。按照惯例,内部会写入 self._age

2) 读写

class C(object):
    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
       assert value >= 0
       self._age = value

只有在赋值时需要进行额外的计算或检查时,才有必要同时使用获取器和设置器。如果没有这些需求,你可以直接声明一个没有下划线的变量,因为属性和实例变量在代码中访问的方式是一样的。所以 _age 和属性 age 当然需要命名不同。

7

一些面向对象的编程语言有一种叫做私有属性,这种属性不能在类的方法外部访问。这很重要,因为有些属性不应该被直接修改,而是应该根据其他东西来改变,或者在改变之前需要进行验证。在Python中没有真正的私有属性,但你可以通过使用以下划线开头的变量来实现类似的效果,这就是Python对私有方法和属性的约定。

举个例子,直角三角形的斜边可以用公式h=sqrt(a*a+b*b)来计算,所以你不能直接改变h,因为这个关系必须保持一致。另外,比如说一个名字必须是LASTNAME COMMA FIRSTNAME的格式,那么在你给self.lastname赋值之前,你需要先验证这个格式是否正确。

属性的获取器让你可以获取斜边的值,但不允许你直接设置它。属性的设置器则允许你设置一个属性,但你可以在实际设置之前进行一些检查。

所以:

class Person(object)
 def __init__(self):
  # The actual attribute is _name
  self._name = None
 @property
 def name(self):
  # when I ask for the name, I mean to get _name
  return self._name
 @name.setter
 def name(self, value):
  # before setting name I can ensure that it has the right format
  if regex_name.match(value):
   # assume you have a regular expression to check for the name
   self._name = value
  else:
   raise ValueError('invalid name')

另一个例子:

class Triangle(object):
 def __init__(self, a, b):
  # here a and b do not need to be private because
  # we can change them at will. However, you could
  # make them private and ensure that they are floats
  # when they are changed
  self.a = a 
  self.b = b
 @property
 def h(self):
  return math.sqrt(a*a+b*b)
 # notice there is no h.setter - you cannot set h directly
12

self.age这个名字已经被属性占用了,所以你需要给实际的变量起个不同的名字,这里用的是_age

顺便说一下,从Python 2.6开始,你可以用装饰器来写这个:

def newprops(object):

    @property
    def age(self):
        return 40

    @age.setter
    def age(self, value):
        self._age = value

撰写回答