【问题标题】:How to deal with mappingproxy when working with class methods?使用类方法时如何处理映射代理?
【发布时间】:2021-09-30 10:01:03
【问题描述】:

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

我在类方法中添加了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() 的情况。

【问题讨论】:

    标签: python class oop methods class-method


    【解决方案1】:

    现有代码的问题在于,就目前而言,您的 red_circle 方法正试图改变 circle 类的属性,而不是 任何一个实例的属性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):
            new_circle = cls()
            new_circle.change_color('red')
            return new_circle
    

    这里有几点需要注意:

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

    mappingproxy 对象

    mappingproxy 对象是(在这里稍微简化一下)不可变字典。普通字典用于实例字典,mappingproxy 对象用于类字典。这里有一个很好的解释,解释了为什么将不同类型的字典用于类 dict:Why is a class __dict__ a mappingproxy?

    类字典与实例字典

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

    你可以在here找到不同种类的python方法的很好的入门教程。

    【讨论】:

    • 嗨,Alex,感谢您提供如此详细的回答!这样的答案正是我所希望的。你最后链接的文章是我迄今为止一直用来解决这个问题的文章哈哈,我同意这是一个非常好的入门教程
    • 别担心,很高兴我能帮上忙!
    猜你喜欢
    • 1970-01-01
    • 2022-01-05
    • 2018-05-20
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    相关资源
    最近更新 更多