Python变量何时直接指向内存,何时通过另一个变量间接指向内存?
在上面的示例中,变量Python变量何时直接指向内存,何时通过另一个变量间接指向内存?,python,Python,在上面的示例中,变量second似乎直接指向30的内存地址,当first被重新分配时,它对second没有影响 first = 30 second = first first = 20 print("first: ", first, "second: ", second) # first: 20 second: 30 然而,在上面的示例中,当我将40分配给Circle.pi时,它会影响circle1.pi,因为circle1.pi指向Circle.pi而不是3.1419的内存地址 Pyth
second
似乎直接指向30的内存地址,当first
被重新分配时,它对second
没有影响
first = 30
second = first
first = 20
print("first: ", first, "second: ", second)
# first: 20 second: 30
然而,在上面的示例中,当我将
40
分配给Circle.pi
时,它会影响circle1.pi
,因为circle1.pi
指向Circle.pi
而不是3.1419
的内存地址 Python在这方面的语义可能会让来自具有显式指针的语言的人感到惊讶,但规则并不复杂
first = 30
second = first
first = 20
print("first: ", first, "second: ", second)
# first: 20 second: 30
我强烈推荐你读内德·巴奇尔德的书
简而言之,Python将名称与值相关联。不可变值(如第一个示例中的整数)无法更改,因此指向该值的多个名称不会相互影响。然而:
如果一个可变的值有多个名称,并且该值发生更改,则所有名称都会看到更改
这就是您在基于类的示例中看到的。还可以通过以下列表查看:
class Circle:
pi = 3.1419
circle1 = Circle()
circle2 = Circle()
circle2.pi = 10
print(Circle.pi, circle1.pi, circle2.pi)
# 3.1419 3.1419 10
Circle.pi = 40
print(Circle.pi, circle1.pi, circle2.pi)
# 40 40 10
编辑:从您的
课程中
示例:
pi
是Circle
class的class属性circle2.pi
pi
不会从代码中修改,circle2.pi=10
,它会创建一个与类属性同名的实例属性,pi
Python的语言语义不是用指针定义的。实现中涉及指针,但不应将变量视为指针。尤其不应将属性视为指针,因为属性访问对此有太多的回退和自定义挂钩。只需编辑即可。这更好吗?一个诡辩:
circle1.pi
不是指向Circle.pi
,而是Circle.pi
。如前所述,circle1
没有属性pi
,因此当您尝试访问circle1.pi
时,查找将取决于类对象。如果您编写例如circle1.pi=7
,您将向circle1
添加一个属性,但不会对Circle
本身进行变异。@ScottyBlades他们是“同一个”,因为当circle1
没有属性pi
时编写circle1.pi
(即circle1.\uuuu dict\uuuuu
不包含pi
的条目)转换为类对象上的查找(即Circle.pi
)基本上,编写circle1.pi
会导致检查circle1.\uuuu dict\uuuuu
,如果失败,则检查circle1.\uuu class\uuuuu.\uu dict\uuu
。如果两者都不包含pi
,则会引发属性错误。
。也没有必要大喊大叫。这样说也有点误导“不能从对象中修改类属性”。任何给定对象的类型对象都可以访问(和修改)类似地,如果属性、元类或其他细节起作用,circle1.pi=40
可以很好地改变类对象本身。我意识到这些都是迂腐的观点,但特别是对于像这样的问题,它值得精确。@Brian我同意这个短语可能会误导。无论如何,非在OP的例子中,你提到的这些东西中有一个在起作用。我不知道为什么你会因为粗体斜体样式而生气,但是如果你这样做了,我道歉。我会删除这些。