Python 变量声明

新手上路,请多包涵

我想澄清如何在 Python 中声明变量。

  1. 我已经看到 变量声明
class writer:
     path = ""

有时,没有明确的声明,而只是使用 __init__ 进行初始化:

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

我了解 __init__ 的目的,但是是否建议在任何其他函数中声明变量?

  1. 如何创建一个变量来保存自定义类型?
 class writer:
    path = "" # string value
    customObj = ??

原文由 bsr 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 708
2 个回答

好吧,第一件事。

Python 中没有“变量声明”或“变量初始化”之类的东西。

简单来说就是我们所说的“分配”,但可能应该只称为“命名”。

赋值的意思是“左边的这个名字现在指的是评估右边的结果,不管它以前指的是什么(如果有的话)”。

 foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

因此,Python 的名称(可以说是比“变量”更好的术语)没有关联的类型。价值观确实如此。无论其类型如何,您都可以将相同的名称重新应用于任何事物,但事物仍然具有取决于其类型的行为。名称只是一种引用值(对象)的方式。这回答了您的第二个问题:您 不会 创建变量来保存自定义类型。您不会创建变量来保存任何特定类型。您根本不会“创建”变量。你给对象命名。

第二点:Python 在类方面遵循一个非常简单的规则,这实际上比 Java、C++ 和 C# 等语言更加一致: class 块中声明的所有内容都是类的一部分。因此,这里编写的函数( def )是方法,即类对象的一部分(不是按实例存储),就像在 Java、C++ 和 C# 中一样;但这里的其他名称 也是 类的一部分。同样,名称只是名称,它们没有关联的类型,并且 函数在 Python 中也是对象。因此:

 class Example:
    data = 42
    def method(self): pass

在 Python 中, 类也是对象

所以现在我们创建了一个名为 Example对象,它代表了所有事物的类 Example s。该对象有两个用户提供的 属性(在 C++ 中,“成员”;在 C# 中,“字段或属性或方法”;在 Java 中,“字段或方法”)。其中一个名为 data ,它存储整数值 42 。另一个名为 method ,它存储一个函数对象。 (还有几个 Python 自动添加的属性。)

但是,这些属性仍然不是对象的一部分。从根本上说,一个对象只是一堆更多的名称(属性名称),直到你开始处理那些不能再分割的东西。因此,值可以在一个类的不同实例之间共享,甚至在不同类的对象之间共享,如果您有意设置的话。

让我们创建一个实例:

 x = Example()

现在我们有一个名为 x 的单独对象,它是 Example 的一个实例。 datamethod 实际上不是对象的一部分,但我们仍然可以通过 x 查找它们,因为 Python 在幕后做了一些魔术。当我们查找 method 时,特别是,我们将获得一个“绑定方法”(当我们调用它时, x 自动传递为 self 参数 8f240ef8cc446 ,如果我们直接查找 Example.method 就不会发生这种情况)。

当我们尝试使用 x.data 时会发生什么?

当我们检查它时,它首先在对象中查找。如果在对象中没有找到,Python 会在类中查找。

但是,当我们 分配给 x.data 时,Python 将在对象上创建一个属性。它 不会 替换类的属性。

这允许我们进行 对象 初始化。 Python 将在创建新实例时自动调用类的 __init__ 方法(如果存在)。在此方法中,我们可以简单地分配给属性以在每个对象上设置该属性的初始值:

 class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

现在我们必须在创建 name Example ,并且每个实例都有自己的 name 。每当我们查找实例的 .name 时,Python 将忽略类属性 Example.name ,因为将首先找到实例的属性。

最后一个警告: 修改(突变)和赋值是不同的东西!

在 Python 中,字符串是不可变的。它们不能被修改。当你这样做时:

 a = 'hi '
b = a
a += 'mom'

不会更改 原始的 ‘hi ’ 字符串。这在 Python 中是不可能的。 Instead, you create a new string 'hi mom' , and cause a to stop being a name for 'hi ' , and start being a name for 'hi mom' 相反。 We made b a name for 'hi ' as well, and after re-applying the a name, b is still a name for 'hi ' ,因为 'hi ' 仍然存在并且没有被改变。

但列表可以更改:

 a = [1, 2, 3]
b = a
a += [4]

现在 b 也是 [1, 2, 3, 4],因为我们为 b 命名了与 a 命名相同的名称,然后我们改变了那件事。我们没有为 a 创建一个新列表来命名,因为 Python 只是简单地处理 += 列表。

这对对象很重要,因为如果您将列表作为类属性,并使用实例来修改列表,那么更改将在所有其他实例中“看到”。这是因为 (a) 数据实际上是类对象的一部分,而不是任何实例对象; (b) 因为您正在修改列表并且没有进行简单的分配,所以您没有创建隐藏类属性的新实例属性。

原文由 Karl Knechtel 发布,翻译遵循 CC BY-SA 3.0 许可协议

这可能晚了 6 年,但在 Python 3.5 及更高版本中,您可以像这样声明一个变量类型:

 variable_name: type_name

或这个:

 variable_name # type: shinyType

所以在你的情况下(如果你定义了一个 CustomObject 类),你可以这样做:

 customObj: CustomObject

有关更多信息,请参见 这个那个

原文由 O. Aroesti 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏