如何在Python中为变量创建别名?

14

正常方式:

class A:
    def __init__(self):
        self.a.b.c = 10

    def another_method(self):
        self.a.b.c = self.a.b.c * 10

简化版:

class A:
    def __init__(self):
        self.a.b.c = 10         
        alias self.aliased = self.a.b.c  # Creates an alias 

    def another_method(self):
        self.aliased = self.aliased * 10  # Updates value of self.a.b.c

在Python中如何进行别名处理?我之所以想这样做是为了减少由于变量名过长而导致的混乱。 这是一个多线程环境,因此简单地复制到本地变量不起作用。


2
你的代码根本不是有效的Python代码,我也不理解你使用的符号的语义。例如,self.a.b.c.d.e = 10 应该做什么?运行这行代码后,self.a 应该是什么? - Sven Marnach
1
你为什么一开始就使用(过)长的变量名呢?如果你真的需要进行超过两层嵌套属性访问,那么你的设计肯定存在严重问题。 - schlamar
2个回答

28

解决方案是使用getter和setter方法 - 幸运的是Python有内置的property() 方法来隐藏这种丑陋:

class A:
    def __init__(self):
        self.a.b.c = 10

    @property
    def aliased(self):
        return self.a.b.c

    @aliased.setter
    def aliased(self, value):
        self.a.b.c = value

    def another_method(self):
        self.aliased *= 10  # Updates value of self.a.b.c

通常,像self.a.b.c这样深度嵌套的属性是设计不良的标志 - 你通常不希望类知道与其3个关系远的对象 - 这意味着对给定项的更改可能会导致整个代码库中的问题。更好的想法是尝试让每个类仅处理其周围的类,而不再进一步。


这样的属性还会增加间接性,这会极大地影响性能。它比直接设置属性慢了几个数量级。 - nosklo
@nosklo 显然会有开销,但在大多数情况下这并不重要。 - Gareth Latty
1
“间接寻址比直接寻址慢几个数量级”这种说法非常可疑,需要有支持的证据。 - BadZen

4

Python不会隐式复制任何内容,它只存储引用,因此无论您在哪个环境中使用它,它都可以正常工作。

# this creates a list and stores a *reference* to it:
really_really_long_variable_name = [] 
# this creates another new reference to the *same list*. There's no copy.
alias = really_really_long_variable_name

alias.append('AIB')
print really_really_long_variable_name

您将获得['AIB']

18
问题在于 alias = ['BIB'] 无法更新 really_really_long_variable_name 这个变量名。 - ie.
1
同意,除非使用可变容器作为hack,否则这并不能解决更新值的问题。 - Gareth Latty
1
当然,你不会更新变量。你会更新可变对象。如果你使用字符[],那么你就会创建另一个对象... - nosklo
1
嗯,有很多时候你需要使用返回不同引用的内置函数。一旦发生这种情况,这个解决方案就会失效。 - Dave Kielpinski
4
对于那些过于字面理解“Python 不会隐式复制任何东西”的人,需要注意:a = 1; b = a; a = 2; print(b) 的输出是 1,而 a = 1; b = a; b = 2; print(a) 的输出也是 1。重新分配变量并不会更新其他变量。 - Anton Tarasenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接