Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中以以下方式定义静态变量有什么问题吗?_Python - Fatal编程技术网

在Python中以以下方式定义静态变量有什么问题吗?

在Python中以以下方式定义静态变量有什么问题吗?,python,Python,如果您有一个不变的值,那么仅使用@property定义它并按如下方式返回值是否有任何错误: class Circle: def __init__(self, radius): self.radius = radius @property def pi(self): return 3.14 def area(self): return self.pi * self.radius 既然PI不应该改变,而且值是静态的,那么用@p

如果您有一个不变的值,那么仅使用@property定义它并按如下方式返回值是否有任何错误:

class Circle:
   def __init__(self, radius):
      self.radius = radius

   @property
   def pi(self):
       return  3.14

   def area(self):
        return self.pi * self.radius
既然PI不应该改变,而且值是静态的,那么用@property定义它是否有任何错误,如上图所示

我通常看到的是:

class Circle:
   def __init__(self, radius):
      self.radius = radius
      self.pi = 3.14

   def area(self):
        return self.pi * self.radius

我认识的Python程序员通常避免使用访问器函数,除非他们实际上在执行计算。在这种情况下,最好将变量设置为类的成员:

类圆:
pi=3.14
定义初始(自身,半径):
自半径=半径
# ...

使用属性的问题是:

>>> d = Circle()
>>> d.pi
3.14
>>> d.pi = 3

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d.pi = 3
AttributeError: can't set attribute
>>> Circle.pi = 3
>>> d.pi
3
>d=Circle()
>>>d.pi
3.14
>>>d.pi=3
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
d、 pi=3
AttributeError:无法设置属性
>>>圆1.pi=3
>>>d.pi
3.
您可以使用元类解决此问题:

class NoSet(type):
    def __setattr__(self, name, value):
        if name == 'pi':
            raise Exception("Can't assign")
        else:
            super(NoSet, self).__setattr__(name, value)

class Circle(object):
    __metaclass__ = NoSet

    @property
    def pi(self):
        return 3.14

>>> d = Circle()
>>> d.pi
3.14
>>> d.pi = 3

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    d.pi = 3
AttributeError: can't set attribute
>>> Circle.pi = 3

Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    Circle.pi = 3
  File "<pyshell#43>", line 4, in __setattr__
    raise Exception("Can't assign")
Exception: Can't assign
class-NoSet(类型):
定义设置属性(自身、名称、值):
如果名称='pi':
引发异常(“无法分配”)
其他:
超级(NoSet,self)。\uuuu setattr\uuuu(名称,值)
类圆(对象):
__元类=NoSet
@财产
def pi(自身):
返回3.14
>>>d=圆()
>>>d.pi
3.14
>>>d.pi=3
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
d、 pi=3
AttributeError:无法设置属性
>>>圆1.pi=3
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
圆1.pi=3
文件“”,第4行,在\uuuu setattr中__
引发异常(“无法分配”)
异常:无法分配
要在Python3中使用,请将类定义更改为
类圆(object,metaclass=NoSet):


免责声明:我刚才刚试过这个,它似乎有效。我不能做出任何承诺,因为我没有太多的元类经验。我个人不会这样做,如果只是因为可能有合理的理由让某人更改该值,例如,如果他们需要更高的精度。

如果希望确保该值不可变,可以定义拒绝设置的属性

class Circle:
   _pi = 3.14

   def __init__(self, radius):
      self.radius = radius

   @property
   def pi(self):
       return _pi

   @pi.setter
   def pi(self, value):
        pass

   ...
pi是不可变的

   c = Circle(1)
   c.pi = 5 # The intent is to make it change
   print c.pi # Output: 3.14, it still keeps origin.

的确将其标记为属性的唯一优点是,除非定义了setter,否则很难修改它。关于做计算的访问器函数-情况并非总是如此。。。如果这是一个昂贵的计算,那么它通常应该是一个函数来表示这一点。我认为目的是使它不可变(“静态”),因为您不能重新分配给
@property
方法。这将确保
mycircle.pi
始终返回
3.14
。可以在类级别创建
@属性
,但它有点毛茸茸的。让它成为一个普通的类变量并相信用户不会修改它可能是最简单的。@TigerhawkT3好吧,你可以重新分配给@property,但这是你自己的方式,所以你自己决定吧。。。如果一个人真的对它不安全,或者担心意外赋值,那么使用
\u pi
可能是一种方法,目的是使它不可变。@Samuel好的-你知道-如果有人足够努力-Python中没有任何属性是不可变的?所以,也许你最好的办法就是使用名称扭曲惯例来表示“你真的不应该改变这一点,但如果你这么做了……这是你的问题,不是我的问题”嗯。。。面积!=self.pi*self.radius。。。面积=self.pi*直径