Python:明确声明属性的静态性

时间:2019-01-08 14:12:24

标签: python python-3.x

我来自C ++和Java环境,刚刚开始学习Python,因此是这个问题。 The Zen of Python中有一个引号:

  

显式优于隐式。

那么,有没有一种方法可以一次在Python中显式地声明静态和/或非静态属性?

例如(不完整的python代码):

class BasicClass():
    # Explicit declaration of a attribute shared through the class and instances
    x = 0

    # Explicit declaration of a attribute that I would like to be owned only by the class
    static:
        y = 10

    # Explicit declaration of a attribute that I would like to be owned by every instance individually
    non_static:
        z = 0

    def __init__(self, x, z):
        self.x = x
        self.z = z

a = BasicClass(1, 2)
b = BasicClass(3, 4)

尽管Python中不存在'static'和'non_static'关键字,但这是我想要实现的行为:

  1. 应该通过x以及BasicClass.xa.x访问b.x属性。是所有不同的实例。
  2. 由于y属性是“静态”的,因此应仅由BasicClass实例拥有(并通过该实例访问)。
    • 例如,a.y可以作为对BasicClass.y的引用。
  3. 由于z属性是“非静态的”,因此应通过a.zb.z(二者是不同的实例)进行访问,并且不能直接通过{{1 }},因为它不能具有此属性。

我认为第一个期望的行为是实际发生的事情。

关于第二个,很明显为什么BasicClass这样的属性很重要并且很受欢迎。

关于第三个问题,我知道可以沿着类的方法声明一个属性。但是可以一次全部声明吗?如果没有,为什么?再说一次,如果不是,这样会更好吗?

显式声明y函数内部的所有内容可能会遇到问题,因为我希望不要初始化属性。还是这是C ++ / Java的偏见?

2 个答案:

答案 0 :(得分:1)

Python没有“静态”属性的概念,而不是C ++定义它们的方式。

相反,在实例上执行Python属性查找需要执行以下步骤;如果步骤成功,则确定结果,并跳过进一步的步骤:

  1. 在类(包括完整的MRO层次结构)上检查data descriptor。它们优先于实例属性。绑定描述符,并返回绑定结果。例如。 property object
  2. 如果实例具有其自己的__dict__命名空间,请检查其中的属性
  3. 检查类层次结构上的属性(如果不是数据描述符,则步骤1将对其进行缓存)。如果它是描述符,则将其绑定,例如一个功能势必会在此阶段产生一种方法。
  4. 如果类层次结构中定义了__getattr__方法,则会调用它以查看它是否可以提供结果。

就是这样;从最基本的角度来说,实例和类是分层的名称空间。没有声明属性,它们之所以存在是因为它们只是被使用

可以使用type hinting帮助诸如IDE和静态类型验证器之类的工具检查类型正确性,并且您可以使用此类提示来声明您的类将使用带有指定的类型,例如:

from typing import ClassVar

class BasicClass:
    x: int = 0            # instance and class attribute, with a default value for the class
    y: ClassVar[int] = 10 # explicitly a class attribute
    z: int                # instance attribute

    def __init__(self, x: int, z: int) -> None:
        self.x = x
        self.z = z

但是Python运行时不会强制执行有关可以在何处设置哪些属性的任何规则。但是,当您在将y的实例上设置BasicClass的代码上运行它时,像mypy这样的静态类型检查器将引发错误:

$ tail -n 2 thdemo.py  # two lines added to the above example
a = BasicClass(42, 81)
a.y = 117
$ mypy thdemo.py
thdemo.py:14: error: Cannot assign to class variable "y" via instance

如果您不使用类型提示,那么您就不必“声明”属性。属性只是“是”,您可以使用它们,也可以不使用。 Python假设我们都是成年人,可以在必要时编写单元测试,否则几乎完全是动态的。这为您提供了很大的灵活性和力量,可以执行在C ++或Java中更加困难和冗长的工作。

答案 1 :(得分:0)

Python很简单,不需要静态关键字。

在类声明中分配的变量是类变量或静态变量,而在类方法内部的变量是实例变量。

class Employee:
   empName = 'Vicky' #class variable

   def __init__(self, age, id):
        self.age = age                #instance variable
        self.id = id                  #instance variable

one = Employee(21, 1)
two = Employee(30, 2)

print(one.empName) # prints "Vicky"
print(one.age) # prints 21