错误地不给自己设定价值观。

2024-04-18 18:04:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚把脚趾伸进Python池。我理解类和名称空间是如何交互的,而del只是从范围中删除了一些东西,以及所有这些好处。你知道吗

我的问题很简单。我制作了一个简单的“hello world”(Pygame)应用程序,但犯了一个严重错误(下面是一个简单的例子):

class Cat:
  __name = ""
  def __init__(self, newName):
    __name = newName
  def meow(self):
    print "Hi from {0}".format(self.__name)

c = Cat("Mittens")
c.meow(); # prints: "Hi from "

事后看来,我的错误是显而易见的:在我的方法(这里特别是构造函数)中,我将一个值赋给了__name,而不是__self.name(顺便说一句,它应该是损坏的和私有的)。你知道吗

我甚至理解它是如何工作的以及为什么工作的——这有点像Java/C中的静态作用域。你知道吗

我不明白的是如何避免这些狡猾的错误。这是显而易见的,简单的,结果是,在我的情况下,什么都没有——事情本来应该有效,但什么都没有发生。你知道吗

Python开发人员如何避免这个问题?似乎这很常见。你知道吗


Tags: namefromself名称helloworlddef错误
2条回答

在这种情况下,我绝对不会将__name添加到类名称空间。由于__name是(应该是)由初始值设定项(__init__)无条件设置的,因此拥有类级别__name是没有意义的。你知道吗

例如:

class Cat:
  def __init__(self, newName):
    __name = newName
  def meow(self):
    print "Hi from {0}".format(self.__name)

c = Cat("Mittens")
c.meow() # prints: "Hi from "

现在运行代码,您将得到一个AttributeError,它有助于捕获这些类型的bug。你知道吗

换句话说,代码中__init__的目的是通过self.__name = newName在正在初始化的新实例(self)上设置__name。在代码中,您通过在类上设置__name来提供一个“安全网”。在python中,如果在实例中找不到某个属性,则会在类中查找该属性。然而,这个“安全网”实际上是一件坏事,在这种情况下,您得到的行为与您预期的不同,而不是一个可以用来帮助您跟踪bug的异常。你知道吗


顺便说一句,实例上的属性访问的工作方式(有一些有趣的事情,比如__getattribute__)是python首先在实例上查找属性,然后搜索类,然后按照类的方法解析顺序工作(这对于新旧样式的类是不同的)。你知道吗

静态分析工具,如pep8pylintpyflakesflake8可以在一定程度上提供帮助。例如,pyflakes会抱怨您的代码(放在名为stack_overflow-2013-03-08.py的文件中):

$ pyflakes stack_overflow-2013-03-08.py
stack_overflow-2013-03-08.py:8: local variable '__name' is assigned to but never used

但是没有什么能胜过一套好的tests。不用说,如果您对Cat.meow的测试合理地覆盖了它的功能范围,那么您就会发现这个问题right meow。你知道吗

相关问题 更多 >