在方法中用同一类型的另一个对象替换自身对象是否安全?

时间:2009-08-01 10:42:21

标签: python

我想在像这样的方法中用另一个实例替换一个对象实例:

class A:
    def method1(self):
        self = func(self)

从数据库中检索对象。

8 个答案:

答案 0 :(得分:51)

替换'self'变量不太可能完成你想要做的任何事情,这不可能通过将func(self)的结果存储在不同的变量中来实现。 'self'实际上是一个局部变量,仅在方法调用的持续时间内定义,用于传入正在操作的类的实例。替换self实际上不会替换对其他对象所持有的类的原始实例的引用,也不会创建对分配给它的新实例的持久引用。

答案 1 :(得分:15)

据我所知,如果您尝试用成员函数替换当前对象与另一个相同类型的对象(假设func不会更改对象类型)。我认为这将实现那个

class A:
    def method1(self):
        newObj = func(self)
        self.__dict__.update(newObj.__dict__)

答案 2 :(得分:10)

这不是这个问题的直接答案,但在下面的帖子中,有一个解决方案可以解决amirouche试图做的事情:

这是工作代码示例(Python 3.2.5)。

class Men:
    def __init__(self, name):
        self.name = name

    def who_are_you(self):
        print("I'm a men! My name is " + self.name)

    def cast_to(self, sex, name):
        self.__class__ = sex
        self.name = name

    def method_unique_to_men(self):
        print('I made The Matrix')


class Women:
    def __init__(self, name):
        self.name = name

    def who_are_you(self):
        print("I'm a women! My name is " + self.name)

    def method_unique_to_women(self):
        print('I made Cloud Atlas')


men = Men('Larry')
men.who_are_you()
#>>> I'm a men! My name is Larry
men.method_unique_to_men()
#>>> I made The Matrix


men.cast_to(Women, 'Lana')
men.who_are_you()
#>>> I'm a women! My name is Lana
men.method_unique_to_women()
#>>> I made Cloud Atlas

请注意self.__class__而非self.__class__.__name__。即这种技术不仅取代了类名,而且实际上转换了一个类的实例(至少它们都有相同的id())。另外,1)我不知道在[对象拥有]方法中用另一个相同类型的对象替换自身对象是否安全“; 2)它适用于不同类型的对象,不仅适用于相同类型的对象; 3)它的工作方式并不像amirouche那样:你不能像Class(args)那样初级化,只能Class()(我不是专业人士,也不能回答为什么会这样)。

答案 3 :(得分:6)

是的,所有这一切都将导致您无法引用班级A的当前实例(除非您在更改之前将另一个变量设置为self。)我不会但是不推荐它,它会降低代码的可读性。

请注意,您只需更改变量,就像其他变量一样。执行self = 123与执行abc = 123相同。 self仅是对方法中当前实例的引用。您无法通过设置self来更改实例。

func(self)应该做的是更改实例的变量:

def func(obj):
    obj.var_a = 123
    obj.var_b = 'abc'

然后这样做:

class A:
    def method1(self):
        func(self) # No need to assign self here

答案 4 :(得分:0)

可以在方法中使用自我赋值,将实例类更改为派生类。

当然可以将它分配给一个新对象,但是新对象的使用会涟漪通过方法中的其余代码。将它重新指向自我,使方法的其余部分保持不变。

class aclass:

    def methodA(self):
        ...
        if condition:
            self = replace_by_derived(self)
            # self is now referencing to an instance of a derived class
            # with probably the same values for its data attributes

        # all code here remains untouched
        ...
        self.methodB() # calls the methodB of derivedclass is condition is True
        ...

    def methodB(self):
        # methodB of class aclass
        ...

class derivedclass(aclass):
    def methodB(self):
        #methodB of class derivedclass
        ...

但除了这样一个特殊用例外,我认为取代自我没有任何好处。

答案 5 :(得分:0)

是的,这没有任何问题。愤世嫉俗的人看什么都不顺眼。 (用你的in most cases imaginable, there's no point in such reassignment and it indicates an error看着你的Pycharm。

您可以这样做的情况是:

some_method(self, ...):

    ...

    if(some_condition):
        self = self.some_other_method()

    ...

    return ...

当然,您可以通过将self重新分配给其他变量来启动方法体,但如果您通常不会对其他参数执行此操作,为什么要使用self

答案 6 :(得分:0)

在许多情况下,实现所需目标的一种好方法是再次调用__init__。例如:

class MyList(list):
    def trim(self,n):
        self.__init__(self[:-n])

x = MyList([1,2,3,4])
x.trim(2)
assert type(x) == MyList
assert x == [1,2]

请注意,这带有一些假设,例如关于__init__中设置的对象的全部更改。

答案 7 :(得分:0)

您可以使实例成为类的单例元素 并用@classmethod标记方法。

from enum import IntEnum
from collections import namedtuple

class kind(IntEnum):
    circle = 1
    square = 2

def attr(y): return [getattr(y, x) for x in 'k l b u r'.split()]

class Shape(namedtuple('Shape', 'k,l,b,u,r')):
    self = None

    @classmethod
    def __repr__(cls):
        return "<Shape({},{},{},{},{}) object at {}>".format(
            *(attr(cls.self)+[id(cls.self)]))

    @classmethod
    def transform(cls, func):
        cls.self = cls.self._replace(**func(cls.self))

Shape.self = Shape(k=1, l=2, b=3, u=4, r=5)
s = Shape.self

def nextkind(self):
    return {'k': self.k+1}

print(repr(s))  # <Shape(1,2,3,4,5) object at 139766656561792>
s.transform(nextkind)
print(repr(s))  # <Shape(2,2,3,4,5) object at 139766656561888>