python - 尽管我没有创建类的实例,但为什么要从类中打印(x)?
问题描述
x = 5
class A:
x += 1 # here we can access and change the value of x in class but only for class
print(f"x from inside class is {x}")
print(x)
为什么在类中打印虽然我没有从类 A 中创建实例
解决方案
Python 代码从上到下执行。该语句触发创建一个新的类对象,当达到 unindent 时class A
,该对象将被最终确定并分配给全局名称。A
通过在单独的隔离命名空间中运行类主体中的所有语句来创建一个类。一旦类主体完成执行,命名空间就被包装到一个类对象中。结果可以由metaclass预处理,但仅此而已。
该语句x += 1
大致相当于x = x.__iadd__(1)
. 扩充的赋值发生在类命名空间内。它不会影响全局名称x
,因为赋值发生在类命名空间中并且整数是不可变的。不变性很重要,因为该x
赋值右侧的 来自全局命名空间,即使左侧不是。
像列表这样的可变对象会以不同的方式工作。Ifx
是一个列表,x += [1]
会将 的结果重新分配x.__iadd__([1])
给一个类变量x
,就像整数情况一样。但是,该操作__iadd__
会就地修改列表对象。这意味着全局x
和A.x
将引用相同的扩展列表。
class
语句,就像语句一样,def
是赋值操作。你告诉解释器运行一个初始化你的类的代码片段。这与 不同def
,后者不运行您编写的任何代码行,而是将它们编译成函数对象。
当解释器创建类命名空间时,您会看到打印输出。该类以一个名为x
set to的变量结束6
。如果你有def
语句,那么类命名空间中也会有函数。如果您尝试通过类的实例访问这些函数,它们将被绑定为方法,因为函数对象是非数据描述符。
推荐阅读
- azure-data-factory-2 - 在 Azure 数据工厂中动态添加两个 json 值
- django - Django MPTT 模型 REST API 在没有服务器重启的情况下不会刷新
- sparql - 在 wikidata SPARQL 查询中如何处理文件?
- node.js - 从前端访问后端 api 时获取 IDX10205
- azure - 如何将出站流量从与包含服务端点的 VNet 集成的应用服务路由到外部 Azure 托管 API?
- r - 如何根据因子变量中的一个类别过滤 geom_text?
- python - 如何验证给定 json 结构的 json 模式
- apache-spark - 将 Azure Databricks 增量表迁移到 Azure Synapse SQL 池
- javascript - 如何比较嵌套数组和常规数组?
- function - 需要最多两位小数的结果,即 jmeter 中的秒和毫秒