学习python,并有一些基本的疑问。
1.我已经看到变量声明(此处的路径)为
class writer:
path = ""
有时,没有明确的声明,但通过__init__
进行初始化。
def __init__(self, name):
self.name = name
我理解__init__
的目的,但建议在任何其他函数中声明变量。
2.如何创建变量来保存自定义类型?
class writer:
path = "" # string value
customObj = ??
答案 0 :(得分:176)
好的,首先要做的事情。
没有"变量声明"或"变量初始化"在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的名称(比#34;变量和#34;更好的术语)没有关联类型;价值观。您可以将相同的名称重新应用于任何类型,无论其类型如何,但事物的行为仍然取决于其类型。该名称只是一种引用值(对象)的方法。这回答了您的第二个问题:您不创建变量来保存自定义类型。您不能创建变量来保存任何特定类型。你不会创造"变量。你给对象命名。
第二点:当涉及到类时,Python遵循一个非常简单的规则,实际上比Java,C ++和C#等语言更加一致:在class
块内声明的所有内容都是班级。因此,这里编写的函数(def
)是方法,即类对象的一部分(不是基于每个实例存储),就像在Java,C ++和C#中一样;但这里的其他名字是也是类的一部分。同样,这些名称只是名称,而且它们没有相关的类型,而函数在Python中也是的对象。因此:
class Example:
data = 42
def method(self): pass
在Python中,类也是对象。
现在我们创建了一个名为Example
的对象,它代表Example
所有内容的类。该对象有两个用户提供的属性(在C ++中,"成员&#34 ;;在C#中,"字段或属性或方法&#34 ;;在Java中," ;字段或方法")。其中一个名为data
,它存储整数值42
。另一个名为method
,它存储一个函数对象。 (Python会自动添加更多属性。)
但是,这些属性仍然不是对象的一部分。从根本上说,一个对象只是一组更多的名称(属性名称),直到你得到的东西不能被分割。因此,如果您故意设置了值,则可以在类的不同实例之间共享值,甚至可以在不同类的对象之间共享。
让我们创建一个实例:
x = Example()
现在我们有一个名为x
的单独对象,它是Example
的一个实例。 data
和method
实际上不是对象的一部分,但我们仍然可以通过x
查找它们,因为Python在幕后做了一些魔术。特别是当我们查找method
时,我们将获得一个"绑定方法" (当我们调用它时,x
会自动作为self
参数传递,如果我们直接查找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
。每当我们查找实例的Example.name
时,Python都会忽略类属性.name
,因为将首先找到实例的属性。
最后一点需要注意:修改(变异)和分配是不同的事情!
在Python中,字符串是不可变的。它们无法修改。当你这样做时:
a = 'hi '
b = a
a += 'mom'
你不要改变原来的' hi'串。这在Python中是不可能的。相反,您创建了新字符串'hi mom'
,并导致a
不再是'hi '
的名称,并开始成为'hi mom'
的名称代替。我们也为b
添加了'hi '
名称,重新应用a
名称后,b
仍然是'hi '
的名称,因为{{ 1}}仍然存在且未被更改。
但是可以更改列表:
'hi '
现在a = [1, 2, 3]
b = a
a += [4]
也是[1,2,3,4],因为我们b
为b
命名的同一个名称做了a
,然后我们改变了那个东西。我们没有为a
创建一个新列表来命名,因为Python只是以不同的方式对列表进行处理。
这对于对象很重要,因为如果你有一个列表作为一个类属性,并使用一个实例来修改列表,那么这个改变将被"看到"在所有其他情况下。这是因为(a)数据实际上是类对象的一部分,而不是任何实例对象; (b)因为您正在修改列表而没有进行简单的赋值,所以您没有创建隐藏class属性的新实例属性。
答案 1 :(得分:21)
无需在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级文档的麻烦,但至少有一些关于你或其他人可能需要提取它的细节的评论。
答案 2 :(得分:10)
这可能要晚6年了,但是在Python 3.5及更高版本中,您需要声明这样的变量类型:
variable_name: type_name
或者这个:
variable_name # type: shinyType
因此,在您的情况下(如果定义了CustomObject
类,则可以执行以下操作:
customObj: CustomObject
答案 3 :(得分:6)
为了确定范围,我使用 -
custom_object =无
答案 4 :(得分:1)
变量具有范围,所以是的,具有特定于您的函数的变量是合适的。你并不总是要明确他们的定义;通常你可以使用它们。只有当你想要做一些特定于变量类型的事情时,比如追加列表,你需要在开始使用它们之前定义它们。典型的例子。
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()
答案 5 :(得分:0)
从 Python 3 开始,您可以按类型显式声明变量。
例如,要声明一个整数,可以这样做:
x: int = 3
或:
def f(x: int):
return x
有关它的更多详细信息,请参阅此问题: Explicitly declaring a variable type in Python