如何解决当引用成为引用对象时,如何使python对象自身或属性不分配给引用对象?
我希望当一个对象被另一个对象,引用者的自身对象或其属性之一引用时,在引用者对象上不同
这就是我想要做的:
class MyClass:
.
.
.
.
a = MyClass()
b = a
print(b is a) #must print false
print(b == a) #must print true
#or
a = MyClass()
b = a
print(b.attr is a.attr) #must print false
print(b.attr == a.attr) #must print true
我该如何实现这一目标,通常是在进行a = b
之类的任务时,b
是对a
的引用,希望得到任何帮助,我希望{{1} }是b
的副本/深拷贝,与属性相同
从现在开始感谢将要回答问题的人
注意:我正在使用cpython(Python的官方实现)版本Python 3.8
我愿意使用黑魔法
解决方法
您不应该尝试对重载分配做任何事情,因为那不是很pythonic。使用deepcopy
函数或复制一个“构造函数”。然后覆盖__eq__
函数,以使两个变量测试相等。
以您建议的方式重载赋值运算符不是很pythonic。
Python中的赋值运算符旨在引用相同的变量,而不是创建副本。
因此,在某些情况下,例如hash(object.attr)
的结果或在该对象上使用pickle
模块所产生的结果,此类对象可能无法达到预期的效果。
但是,如果您想要一些黑魔法...
要清楚,我提供这个答案只是为了证明Python确实具有执行此类操作的能力。
一种方法是在访问任何属性时使用__getattribute__()
函数创建一个副本。
import copy
class MyClass:
def __init__(self):
self.attr = ["foo","bar"]
def __getattribute__(self,name):
"""Access an attribute of this class"""
attr = object.__getattribute__(self,name)
return copy.copy(attr)
a = MyClass()
b = a
print(b.attr is a.attr) # prints False
print(b.attr == a.attr) # prints True
有关__getattribute__()
的更多信息,请参见:https://docs.python.org/3/reference/datamodel.html
或者,property()
仅可用于类上的单个属性。
class MyClass:
def __init__(self):
self.__attr = ["foo","bar"]
@property
def attr(self):
"""Get the attribute."""
# Copy could be used instead
# This works too,if we assume the attribute supports slicing
return self.__attr[:]
@attr.setter
def attr(self,value):
"""Setting the attribute."""
# Makes assignment work on this attribute
# a.attr = []
# a.attr is a.attr (False)
self.__attr = value
a = MyClass()
b = a
print(b.attr is a.attr) # prints False
print(b.attr == a.attr) # prints True
这些解决方案适用于大多数对象类型。但这实际上在某些情况下会失败。这是因为某些字符串和一些整数将被标记为具有相同的标识。
例如4 is 2*2
,将是True
,但是
a = -6
b = -6
print(a is b) # Will print False
这称为“实习”,并在sys
模块中简要讨论:https://docs.python.org/3/library/sys.html?highlight=intern#sys.intern
根据Real Python:https://realpython.com/lessons/intern-objects/
在CPython 3.7中,-5和256之间的整数被插入,与 少于20个字符且仅包含ASCII的字符串 字母,数字或下划线。
例如,如果attr = 5
或attr = 'foo'
,则上述两种方法都将失败。
a = MyClass()
a.attr = 5
b = a
print(b.attr is a.attr) # prints True
print(b.attr == a.attr) # prints True
可以通过将这些类型包装在子类中来避免这种情况。根据RealPython,仅需修改字符串和一些整数。这种方法的不足之处在于类型比较会失败:
print(type(b.attr) is type(a.attr)) # prints False
因此,如果要包装对象,请确保is
操作始终失败,则可以执行以下操作:
import copy
from collections import UserString # Because of course Python has this built in
class UserInt(int): pass
class MyClass:
def __init__(self,attr = ["foo","bar"]):
self.attr = attr
def __getattribute__(self,name)
if isinstance(attr,int) and -5 <= attr <= 256:
return UserInt(attr) # Prevent a.attr is b.attr if this is an int
elif isinstance(attr,str):
return UserString(attr) # Prevent a.attr is b.attr for strings
#else
return copy.copy(attr)
a = MyClass()
b = a
print(b.attr is a.attr) # prints False
print(b.attr == a.attr) # prints True
a.attr = 7
b = a
print(b.attr is a.attr) # prints False
print(b.attr == a.attr) # prints True
a.attr = "Hello"
print(b.attr is a.attr) # prints False
print(b.attr == a.attr) # prints True
,
可以用于例如:copy.copy和copy.deepcopy ...
对于python3:
print(MyClass() == MyClass())
print(MyClass() is MyClass())
出局:
False
False
>>>
和其他萨满法将是类似的...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。