简体   繁体   English

将类实例分配给python中的类属性是一种好习惯吗?

[英]is it a good practice to assign a class instance to a class attribute in python?

I'm trying to use class composition in python, and I wonder if it is a good practice to assign a class instance to a class attribute in python. 我正在尝试在python中使用类组合,而我想知道是否为python中的类属性分配类实例是一种好习惯。 Below are the 2 examples which I have in mind. 以下是我想到的两个示例。 I appreciate if some experienced programmers could tell me when to use which. 如果某些经验丰富的程序员可以告诉我何时使用它,我将不胜感激。

(1) (1)

class A:
   def __init__(self):
      self.x = 10

class B:
   def __init__(self):
      self.y = A()

objB = B()

(2) (2)

class A:
   def __init__(self):
      self.x = 10

class B:
   def __init__(self):
      self.y = None

objB = B()
objB.y = A()

Things like this are ALWAYS descriptive! 这样的事情总是描述性的! Does every B have an A object? 每个B是否都有一个A对象? If so, then you'd better use #1. 如果是这样,那么您最好使用#1。 Is B some kind of container, that in THIS case has an A object? B是某种容器,在这种情况下具有A对象? Use #2. 使用#2。

As an example, imagine I'm building a map of Tile objects. 例如,假设我正在构建Tile对象的地图。 Each Tile object has a location , which I'm further abstracting into a Location object like so: 每个Tile对象都有一个location ,我将其进一步抽象为一个Location对象,如下所示:

class Tile(object):
    def __init__(self, location, *args, **kwargs):
        self.location = location

class Location(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

x2_y3 = Location(2, 3)
tile = Tile(x2_y3)
tile.location.x # 2

Now I could ALSO do this as: 现在我也可以这样做:

class Tile(object):
    def __init__(self, location: "(x, y)", *args, **kwargs):
        x, y = location
        self.location = Location(x, y)

class Location(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

tile = Tile(2,3) # builds its own location object

The second strategy may be preferable in this situation, but I prefer the first because it's more expandable. 在这种情况下,第二种策略可能更可取,但我更喜欢第一种,因为它更具扩展性。 If later on I move to 3D space I can instead do: 如果以后再移至3D空间,则可以执行以下操作:

class Location3D(Location):
    def __init__(self, x, y, z):
        self.z = z
        super().__init__(x, y)

tile = Tile(Location3D(2, 3, -1))

In the second strategy, this would fail because Tile s ALWAYS have Location objects. 在第二种策略中,这将失败,因为Tile始终具有Location对象。 You'd have to monkey-patch Tile to make that work, or build a new Tile3D object that may or may not play nice with other Tile s. 您必须猴子修补Tile才能使其正常工作,或者构建一个新的Tile3D对象,该对象可能与其他Tile不能很好地配合使用。

re. 回覆。 1), I would explicitly pass in the A instance, rather than build it within B.__init__. 1),我将显式传递A实例,而不是在B .__ init__中构建它。 The reason is that, with non-trivial cases, you will want to have different initialization values for A. Or else you might want a shared A instance - otherwise, it's a 1-1 relationship which is restrictive. 原因是,在非平凡的情况下,您将希望对A具有不同的初始化值。否则,可能需要共享的A实例-否则,这是1-1关系,这是限制性的。

class A:
   def __init__(self):
      self.x = 10

class B:
   def __init__(self, instanceA):
      self.y = instanceA

#fire-and forget A
objB = B(A())

#can still do something with the instance
a = A()
objB2 = B(a)

For example, I often work with B classes that have either a 'manager' or a 'parent' attribute. 例如,我经常使用具有'manager'或'parent'属性的B类。 Say, a Table class that has n Column children. 假设一个Table类有n个Column子级。 Each column gets a reference to the parent table, they don't make one up on the fly. 每一列都有对父表的引用,但它们并不是动态的。

Further refinement is possible if you mostly don't need to worry about the a instance's initial values: 如果您几乎不需要担心实例的初始值,则可以进行进一步的优化:

class B:
   #instanceA uses a default value of None
   def __init__(self, instanceA = None):
      #assign the instanceA if it was passed or build your own on the fly
      if instanceA is None:
          self.y = A()
      else:
          self.y = instanceA

ps do NOT do this to initiate a default A instance. ps请勿执行此操作以启动默认的A实例。 The default value is only computed once and the same A instance gets assigned whenever you don't explicitly pass in a value. 默认值仅计算一次,并且只要您不显式传递值就将分配相同的A实例。

   def __init__(self, instanceA = A()):
        ....

re. 回覆。 2) I would not use after-the-fact composition. 2)我不会使用事后的构图。 What if you forget to set the .y attribute? 如果您忘记设置.y属性怎么办? instances should, as much as possible, not require multiple chained calls and modifications before they can be used (pretty much what skrrgwasme said). 实例在使用之前应尽可能不要求多个链接的调用和修改(几乎与skrrgwasme所说的一样)。 Python has that flexibility, yes, doesn't mean it should be used without a good reason. Python具有这种灵活性,是的,并不意味着应该在没有充分理由的情况下使用它。

Last, while you don't need to set self.y = None, some Python code analysis tools pick up instance attributes only when they are set on the __init__ method. 最后,虽然不需要设置self.y = None,但是某些Python代码分析工具仅在__init__方法上设置实例属性时才会选择它们。

I would suggest Method 1 because it more strongly supports encapsulation than Method 2. 我建议使用方法1,因为它比方法2更支持封装。

Why do we care about encapsulation? 我们为什么要关心封装? In Method 1, objB can be initialized in a single statement, so there are fewer places to chase down initialization bugs. 在方法1中,可以在单个语句中初始化objB ,因此可以减少追踪初始化错误的地方。 Code that wants to use your class doesn't need to know a series of steps required to initialize it; 想要使用您的类的代码不需要知道初始化它所需的一系列步骤。 just a single statement and an argument list. 只是一个语句和一个参数列表。 This simplicity leads to fewer bugs and more flexible and maintainable code. 这种简单性导致更少的错误以及更灵活和可维护的代码。

Although encapsulation isn't as strongly enforced in Python as it is in some other languages, such as Java, it is still a good practice. 尽管在Python中封装没有像在其他语言(如Java)中那样强强制执行,但这仍然是一个好习惯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Python - 将类属性分配给变量 - Python - Assign class attribute to a variable 用python多继承类实现的好习惯? - A good practice to implement with python multiple inheritance class? 将属性分配给其他测试将使用的测试器类是否是一种好习惯 - Is it a good practice to assign atributes to the tester class that will be used by other tests 我何时以及为什么可以将描述符 class 的实例分配给 Python 中的 class 属性而不是使用属性? - When and why might I assign an instance of a descriptor class to a class attribute in Python rather than use a property? 不可更改的 Python 类实例属性 - Unchangeable Python Class Instance Attribute 在 python 中附加一个 class 实例属性 - Appending to a class instance attribute in python 在类变量中保留对它的当前实例的引用是一种好习惯吗? - Is it a good practice to keep reference in a class variable to the current instance of it? Python - 将类变量指针分配给实例方法 - Python - assign class variable pointer to instance method Python:使用class实例的“值”作为指定class实例属性的值 - Python: Use the "value" of a class instance as the value of a specified class instance attribute 使用python类变量作为dict键是一种好习惯吗? - Using python class variables as dict key is good practice?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM