105

学习Python,有一些基本的疑惑。

1.我已经看到变量声明(此处的路径)为

class writer:
    path = ""

有时,没有显式声明,而是通过__init__.

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

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

2.如何创建变量来保存自定义类型?

class writer:
    path = "" # string value
    customObj = ??
4

6 回答 6

225

好吧,第一件事。

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,它代表了所有事物的类Examples。该对象有两个用户提供的属性(在 C++ 中,“成员”;在 C# 中,“字段或属性或方法”;在 Java 中,“字段或方法”)。其中之一是命名data的,它存储整数值42。另一个名为method,它存储一个函数对象。(还有几个 Python 自动添加的属性。)

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

让我们创建一个实例:

x = Example()

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

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

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

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

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

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

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

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

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

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

不会更改原始的 'hi ' 字符串。这在 Python 中是不可能的。相反,您创建了一个的string 'hi mom',并导致a不再是 的名称,而是'hi '开始成为 的名称。'hi mom'我们也b为ass 起了名字,'hi '重新申请a名字后,b仍然是 for 的名字'hi ',因为'hi '仍然存在,没有改变。

但列表可以更改:

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

现在b也是 [1, 2, 3, 4],因为我们b为命名的同一事物a命名,然后我们更改了该事物。我们没有为ato name 创建一个新列表,因为 Python 只是对列表进行了+=不同的处理。

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

于 2012-06-13T04:43:20.467 回答
29

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

variable_name: type_name

或这个:

variable_name # type: shinyType

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

customObj: CustomObject

有关更多信息,请参阅那个

于 2018-07-04T14:35:18.730 回答
24

无需在 Python 中声明新变量。如果我们谈论的是函数或模块中的变量,则不需要声明。只需为您需要的名称分配一个值:mymagic = "Magic". Python 中的变量可以保存任何类型的值,你不能限制它。

不过,您的问题专门询问了类、对象和实例变量。创建实例变量的惯用方式是在__init__方法中而不是在其他任何地方——虽然您可以在其他方法中,甚至在不相关的代码中创建新的实例变量,但这只是一个坏主意。这将使您的代码难以推理或维护。

例如:

class Thing(object):

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

简单的。现在这个类的实例有一个magic属性:

thingo = Thing("More magic")
# thingo.magic is now "More magic"

在类本身的命名空间中创建变量会导致完全不同的行为。它在功能上有所不同,只有在有特定理由时才应该这样做。例如:

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

现在尝试:

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

或者:

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

这是因为类本身的命名空间与从它创建的对象的命名空间不同。我会把它留给你去研究一下。

带回家的信息是,惯用的 Python 将 (a) 在您的__init__方法中初始化对象属性,并 (b) 根据需要记录您的类的行为。对于您编写的所有内容,您无需为完整的 Sphinx 级文档而烦恼,但至少对您或其他人可能需要了解的任何细节进行一些评论。

于 2012-06-13T03:38:41.130 回答
17

出于范围界定的目的,我使用:

custom_object = None
于 2017-06-22T15:29:48.033 回答
2

变量有范围,所以是的,拥有特定于您的函数的变量是合适的。您不必总是明确说明它们的定义;通常你可以使用它们。只有当你想对变量的类型做一些特定的事情时,比如附加一个列表,你才需要在开始使用它们之前定义它们。这方面的典型例子。

list = []
for i in stuff:
  list.append(i)

顺便说一句,这并不是设置列表的好方法。最好说:

list = [i for i in stuff] # list comprehension

...但我离题了。

你的另一个问题。自定义对象应该是一个类本身。

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
于 2012-06-13T03:12:16.607 回答
1

从 Python 3 开始,您可以按类型显式声明变量。

例如,要声明一个整数,可以这样做:

x: int = 3

或者:

def f(x: int):
    return x

有关它的更多详细信息,请参阅此问题: Explicitly declaring a variable type in Python

于 2021-06-10T12:54:39.733 回答