使用 class 方法时如何处理 mappingproxy?

How to deal with mappingproxy when working with class methods?

我最近一直在尝试使用 class 方法来更好地理解面向对象的编程。作为示例程序的一部分,我有一个名为 circle 的简短 class,可用于创建不同的 circle 实例。

class circle():
    def __init__(self):
        self.radius = 10
        self.color = 'blue'
    def change_color(self, color):
        self.color = color

    @classmethod
    def red_circle(cls):
        circle.radius = 10
        circle.color = 'red'
        return cls

我在 class 方法中添加了 red_circle,这样我就可以为 circle 实例设置不同的默认设置。我遇到的问题是,当我使用 red_circle 方法时,创建的实例被放置在 mappingproxy() 内?例如:

circle_one = circle()
circle_one.__dict__

给出输出:

{'radius': 10, 'color': 'blue'}

但使用

circle_two = circle.red_circle()
circle_two.__dict__

给出:

mappingproxy({'__dict__': <attribute '__dict__' of 'circle' objects>,
              '__doc__': None,
              '__init__': <function __main__.circle.__init__>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'circle' objects>,
              'change_color': <function __main__.circle.change_color>,
              'color': 'orange',
              'radius': 10,
              'red_circle': <classmethod at 0x7f0e94ab1a10>})

有没有办法可以操纵 circle_two 使其看起来与 circle_one 实例相同?它现在没有引起任何问题,但最好了解 mappingproxy().

发生了什么

您现有代码的问题在于您的 red_circle 方法,就目前而言,正试图改变 circle class[=61] 的 属性=] 而不是 circle class.

的任何一个实例的属性

你可以像这样重写它来解决这个问题:

class Circle:
    def __init__(self):
        self.radius = 10
        self.color = 'blue'

    def change_color(self, color):
        self.color = color

    @classmethod
    def red_circle(cls):
        new_circle = cls()
        new_circle.change_color('red')
        return new_circle

这里要注意几点:

  • 我已将您的 circle class 重命名为 Circle。在 python 代码中,将 class 的名称大写是一个强有力的约定,如果不这样做,您可能会使其他程序员感到困惑。
  • 与函数不同,声明 class 时不需要括号,除非您是从另一个 class.
  • 继承的
  • 就像一个实例方法总是将 class 实例作为它的第一个参数(并且有一个强烈的约定总是调用该参数 self),class 方法总是将 class 本身 作为它的第一个参数(并且有一个强烈的约定总是调用该参数 cls ).

mappingproxy 个对象

mappingproxy 对象是(这里稍微简化一下)不可变的字典。普通词典用于实例词典,mappingproxy 对象用于 class 词典。这里有一个很好的解释为什么不同类型的字典用于 class 字典:.

Class 字典与实例字典

在您的 circle class 中,radiuscolor 属性是 instance 属性。 circle 的每个实例都有自己的版本,并将这些版本保存在自己的个性化实例字典中。但是,circle class — __init__change_colorred_circle 中的方法是 class 属性。这些方法保存在 class 字典中 — 您遇到的 mappingproxy 对象。 circle 的所有实例都可以访问相同的 class 字典,这就是它们访问这些方法的方式。

您可以找到关于各种 python 方法的很好的介绍教程 here