使用 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 中,radius
和 color
属性是 instance 属性。 circle
的每个实例都有自己的版本,并将这些版本保存在自己的个性化实例字典中。但是,circle
class — __init__
、change_color
和 red_circle
中的方法是 class 属性。这些方法保存在 class 字典中 — 您遇到的 mappingproxy
对象。 circle
的所有实例都可以访问相同的 class 字典,这就是它们访问这些方法的方式。
您可以找到关于各种 python 方法的很好的介绍教程 here。
我最近一直在尝试使用 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 中,radius
和 color
属性是 instance 属性。 circle
的每个实例都有自己的版本,并将这些版本保存在自己的个性化实例字典中。但是,circle
class — __init__
、change_color
和 red_circle
中的方法是 class 属性。这些方法保存在 class 字典中 — 您遇到的 mappingproxy
对象。 circle
的所有实例都可以访问相同的 class 字典,这就是它们访问这些方法的方式。
您可以找到关于各种 python 方法的很好的介绍教程 here。