有关Python类的初学者问题

时间:2010-06-16 13:32:16

标签: python

我是Python的新手,所以如果我问一些过于无趣的话,请不要激怒我。)

1

考虑我有一个班级:

class Test:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def wow():
        print 5 * 5

现在我尝试创建该类的对象:

x = Test(3, 4)

这可以按预期工作。但是,当我尝试调用方法wow()时,它会返回一个错误,通过将wow()更改为:

来修复
def wow(self)

为什么我需要包含self,如果不包含,该方法的含义是什么?

2。在__init__

的定义中
def __init__(self, x, y):
   self.x = x
   self.y = y

为什么我需要声明x和y,当我可以这样做时:

def __init__(self):
    self.x = x
    self.y = y

我希望我清楚......

感谢您的时间。

6 个答案:

答案 0 :(得分:4)

如果你这样做:

def __init__(self):
  self.x = x
  self.y = y

您将gobal vars x和y(它们存在)分配给您的实例

with:

def __init__(self, x, y):
      self.x = x
      self.y = y

您将作为参数提供的内容分配给构造函数

这更灵活: - )

答案 1 :(得分:2)

Python中的实例引用是显式的。这样它可以通过例如操纵最终传递给方法之前的装饰器。

我们需要声明xy作为函数的参数,以便我们可以在函数中使用它们的名称,绑定到相应函数调用中传递的参数。

答案 2 :(得分:1)

要清楚

  

为什么我需要声明x和y,何时   我可以这样做:

def __init__(self):
    self.x = x
    self.y = y

只有在运行时才能找到x和y时,这个^才有效 - 如果它们没有被传入,那么它们必须已经设置在别处(全局),否则会产生错误。

>>> class c:
    def __init__(self):
        self.x = x

>>> x = 1
>>> q = c()
>>> q.x
1
>>> del x
>>> q.x
1
>>> w = c()

Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    w = c()
  File "<pyshell#14>", line 3, in __init__
    self.x = x
NameError: global name 'x' is not defined
>>> 
>>> w = c(2)

Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    w = c(2)
TypeError: __init__() takes exactly 1 argument (2 given)

这就是您希望/需要将它们指定为参数的原因 - 它可能与全局查找一起使用,但它可能会违反“principle of least astonishment

答案 3 :(得分:1)

self是一个“神奇”的名字 - 它确实可以是任何东西,但是self用于一致性和清晰度。要回答您的问题,每个类方法/函数都需要显式引用该类作为第一个参数。使用Ipython

In [66]: class Test:
   ....:     def __init__(self):
   ....:         pass
   ....:     def wow(self):
   ....:         print self
   ....:
   ....:

In [67]: x = Test()

In [68]: x.wow()
<__main__.Test instance at 0x0159FDF0>

除非您的命名空间中已经有x和y,否则您的第二个示例将无法正常工作。

例如,如果你定义了你的类:

class Test:
    def __init__(self):
        self.x = x
        self.y = y

并尝试了

x = Test()

它将抛出NameError

但是如果你写:

x = 3
y = 4
test = Test()
然后它会起作用。但是,做这样的事情并不是一个好主意。为什么读第2行:

In [72]: import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

答案 4 :(得分:0)

  1. 在Python中,方法应该总是采用“一个额外的”参数,这是对该方法被调用的实例的引用。这在其他语言中是自动的,例如Java,C#等,但Python对此很冗长。

  2. 这没有意义。该示例中的xy在哪里?如果您希望构造函数采用填充对象的两个参数,请将其定义为。否则,你正在做别的事。

答案 5 :(得分:0)

Python与C ++和Java等语言的不同之处在于,对象实例引用是显式传递的。

也就是说,如果您有一个对象是该类的实例,并且您想要调用在该实例上运行的方法(例如,读取其字段),则使用自引用作为对象。

在c ++和Java中,您有一个隐含的“this”引用,它存在于程序的编译版本中,但不存在于源代码中。您可以使用static关键字将其设置为没有“this”的类方法。