我想澄清如何在 Python 中声明变量。
- 我已经看到 变量声明 为
class writer:
path = ""
有时,没有明确的声明,而只是使用 __init__
进行初始化:
def __init__(self, name):
self.name = name
我了解 __init__
的目的,但是是否建议在任何其他函数中声明变量?
- 如何创建一个变量来保存自定义类型?
class writer:
path = "" # string value
customObj = ??
原文由 bsr 发布,翻译遵循 CC BY-SA 4.0 许可协议
好吧,第一件事。
Python 中没有“变量声明”或“变量初始化”之类的东西。
简单来说就是我们所说的“分配”,但可能应该只称为“命名”。
赋值的意思是“左边的这个名字现在指的是评估右边的结果,不管它以前指的是什么(如果有的话)”。
因此,Python 的名称(可以说是比“变量”更好的术语)没有关联的类型。价值观确实如此。无论其类型如何,您都可以将相同的名称重新应用于任何事物,但事物仍然具有取决于其类型的行为。名称只是一种引用值(对象)的方式。这回答了您的第二个问题:您 不会 创建变量来保存自定义类型。您不会创建变量来保存任何特定类型。您根本不会“创建”变量。你给对象命名。
第二点:Python 在类方面遵循一个非常简单的规则,这实际上比 Java、C++ 和 C# 等语言更加一致: 在
class
块中声明的所有内容都是类的一部分。因此,这里编写的函数(def
)是方法,即类对象的一部分(不是按实例存储),就像在 Java、C++ 和 C# 中一样;但这里的其他名称 也是 类的一部分。同样,名称只是名称,它们没有关联的类型,并且 函数在 Python 中也是对象。因此:在 Python 中, 类也是对象。
所以现在我们创建了一个名为
Example
的 对象,它代表了所有事物的类Example
s。该对象有两个用户提供的 属性(在 C++ 中,“成员”;在 C# 中,“字段或属性或方法”;在 Java 中,“字段或方法”)。其中一个名为data
,它存储整数值42
。另一个名为method
,它存储一个函数对象。 (还有几个 Python 自动添加的属性。)但是,这些属性仍然不是对象的一部分。从根本上说,一个对象只是一堆更多的名称(属性名称),直到你开始处理那些不能再分割的东西。因此,值可以在一个类的不同实例之间共享,甚至在不同类的对象之间共享,如果您有意设置的话。
让我们创建一个实例:
现在我们有一个名为
x
的单独对象,它是Example
的一个实例。data
和method
实际上不是对象的一部分,但我们仍然可以通过x
查找它们,因为 Python 在幕后做了一些魔术。当我们查找method
时,特别是,我们将获得一个“绑定方法”(当我们调用它时,x
自动传递为self
参数 8f240ef8cc446 ,如果我们直接查找Example.method
就不会发生这种情况)。当我们尝试使用
x.data
时会发生什么?当我们检查它时,它首先在对象中查找。如果在对象中没有找到,Python 会在类中查找。
但是,当我们 分配给
x.data
时,Python 将在对象上创建一个属性。它 不会 替换类的属性。这允许我们进行 对象 初始化。 Python 将在创建新实例时自动调用类的
__init__
方法(如果存在)。在此方法中,我们可以简单地分配给属性以在每个对象上设置该属性的初始值:现在我们必须在创建
name
Example
,并且每个实例都有自己的name
。每当我们查找实例的.name
时,Python 将忽略类属性Example.name
,因为将首先找到实例的属性。最后一个警告: 修改(突变)和赋值是不同的东西!
在 Python 中,字符串是不可变的。它们不能被修改。当你这样做时:
您 不会更改 原始的 ‘hi ’ 字符串。这在 Python 中是不可能的。 Instead, you create a new string
'hi mom'
, and causea
to stop being a name for'hi '
, and start being a name for'hi mom'
相反。 We madeb
a name for'hi '
as well, and after re-applying thea
name,b
is still a name for'hi '
,因为'hi '
仍然存在并且没有被改变。但列表可以更改:
现在
b
也是 [1, 2, 3, 4],因为我们为b
命名了与a
命名相同的名称,然后我们改变了那件事。我们没有为a
创建一个新列表来命名,因为 Python 只是简单地处理+=
列表。这对对象很重要,因为如果您将列表作为类属性,并使用实例来修改列表,那么更改将在所有其他实例中“看到”。这是因为 (a) 数据实际上是类对象的一部分,而不是任何实例对象; (b) 因为您正在修改列表并且没有进行简单的分配,所以您没有创建隐藏类属性的新实例属性。