初始化对象变量 - Java方法,Python方法?

时间:2011-07-01 11:58:39

标签: python

我有一个对象需要传递4-5个值。举例说明:

class Swoosh():
    spam = ''
    eggs = ''
    swallow = ''
    coconut = ''

    [... methods ...]

目前,使用Swoosh的方式是:

swoosh = Swoosh()
swoosh.set_spam('Spam!')
swoosh.set_eggs('Eggs!')
swoosh.set_swallow('Swallow!')
swoosh.set_coconut('Migrated.')

我怀疑这是Pythonic还是Java影响太大了。还是只是必要的?另外,如果你想知道为什么我使用setter而不是简单地访问对象变量 - 那里必须进行一些基本的验证,因此set_方法。

我认为我可以提供一种不同的方式来初始化Swoosh - 提供一个__init__()来接受dict / list

无论如何,我只是想从更有经验的人那里寻求帮助/建议。

提前感谢您对此的任何意见。

5 个答案:

答案 0 :(得分:15)

首先,您使用的是旧式课程。你真的,真的应该使用new style classes that inherit from object

class Swoosh(object):

定义带参数的__init__方法绝对是Pythonic的做事方式:

def __init__(self,spam,eggs,swallow,coconut):
    self.spam = spam
    self.eggs = eggs
    self.swallow = swallow
    self.coconut = coconut

这将允许你这样做:

s = Swoosh('Spam!','Eggs','Swallow','Migrated')

与任何其他Python函数一样,__init__方法可以具有参数的默认值,例如

def __init__(self,spam,eggs,swallow,coconut='Migrated.'):
        self.spam = spam
        self.eggs = eggs
        self.swallow = swallow
        self.coconut = coconut

如果要在设置属性时验证属性,则应使用标准property attributes而不是创建自己的setter。如果你这样做,你可以在代码中使用myobject.spam,就像使用普通属性一样,但你的setter方法仍在运行。

例如:

@property
def spam(self):
    """I'm the 'spam' property."""
    return self._spam

@spam.setter
def spam(self, value):
    if not value.endswith("!"):
        raise ValueError("spam must end with !")
    # Store the value in "private" _spam attribute
    self._spam = value

@spam.deleter
def spam(self):
    del self._spam

注意:property无法正常工作,除非您使用上述新风格的课程。

在您的示例中,您有:

class Swoosh():
    spam = ''
    eggs = ''
    swallow = ''
    coconut = ''

这通常是一种为对象的属性设置默认值的快速方法。没关系,但你需要了解实际发生的事情。发生了什么事情是你在上设置属性。如果一个对象没有属性,Python将查看它是否在类上定义并从那里返回值(因为这是你想要的方法)。

如果要为对象属性设置默认值,最好如上所述为__init__中的参数设置默认值,而不是使用class属性。

答案 1 :(得分:10)

首先,这个:

class Swoosh():
    spam = ''
    eggs = ''
    swallow = ''
    coconut = ''

设置属性spameggs等。然后,您的set_spam方法可能会继续并创建同名的 object 属性隐藏类属性。换句话说,定义这些属性没有任何效果,只会让事情混淆。

如果所有变量都是可选的,我会这样做:

class Swoosh():
    def __init__(self, spam="", eggs="", swallow="", coconut=""):
        self.spam = spam
        self.eggs = eggs
        self.swallow = swallow
        self.coconut = coconut

然后你可以创建这样的对象:

o1 = Swoosh(eggs="Eggs!", coconut="Carried by the husk")

如果垃圾邮件和鸡蛋是强制性的,那么用

代替
    def __init__(self, spam, eggs, swallow="", coconut=""):

根本不要使用setter和getters。如果您以后需要,可以通过向您的类添加这样的代码,将常规属性无缝替换为属性:

    def get_spam(self):
        return self._spam
    def set_spam(self, value):
        self._spam = " ".join([str(value)] * 5)
    spam = property(get_spam, set_spam)

通过上述更改,即:

o2 = Swoosh(eggs="yes", spam="spam")
print o2.spam

打印

spam spam spam spam spam

注意:正如Dave Webb在他的回答中所指出的那样,除非你使用python 3.0+,否则你需要继承object属性才能工作,在这种情况下,类隐式地为{{{}} 1}}。哦,跟随Sean Vieira链接到 Python不是Java 的文章。这是必读的。

答案 2 :(得分:4)

可以通过覆盖适当的get and set methods on the class(如果需要在所有情况下进行验证)或通过使用内置property更改特定属性来完成基本验证。请记住,Python is not Java(当然,Java is not Python, either)。

至于你想如何创建课程,你有几个选择:

1)使用带有关键字args的__init__方法,让人们尽可能多地提供构造函数:

class Swoosh(object): # Get new-object goodness
    def __init__(self, spam='', eggs='', swallow='', coconut=''):
        # We are going to be using properties in this example
        self._spam = spam
        self._eggs = eggs
        self._swallow = swallow
        self._coconut = coconut

2)继续按照您的方式做事,但将类属性更新为实例属性:

class Swoosh(object): # Get new-object goodness
    def __init__(self):
        self.spam = ''
        self.eggs = ''
        self.swallow = ''
        self.coconut = ''

您目前的工作方式是,Swoosh的每个实例都为这些变量分享相同的值,并且更改spamSwoosh的值会将其更改为 Swoosh的每个实例都没有设置具有相同名称的实例属性(这可能不是您想要的。)

无论哪种方式,你应该考虑删除getter和setter并用属性替换它们(当你这样做时,当然取决于公共和广泛使用这个API的方式):

# Inside class Swoosh's definition
@property
def spam(self):
    return self._spam
@spam.setter
def spam(self, value):
    # Validate that it's really SPAM, not WHAM!
    # And only then replace the underlying value
    self._spam = value
@spam.deleter
def spam(self):
    del self._spam
# Rinse and repeat for other properties that need access control

答案 3 :(得分:3)

要初始化Swoosh值,您有多种选择:

首先,构造函数args:

class Swoosh(object):
   def __init__(self, spam, eggs, swallow, coconut):
      self.spam = spam
      self.eggs = eggs
      self.swallow = swallow
      self.coconut = coconut

然后像这样实现你的目标:

swoosh = Swoosh("spam", "eggs", "swallow", "coconut")

如果您需要更多控制获取/设置值的方式,可以使用property方法。

class Swoosh():
   def __init__(self, spam, eggs, swallow, coconut):
      self.spam = spam
      self.eggs = eggs
      self.swallow = swallow
      self.coconut = coconut

  def set_spam(self, value):
     #do verification stuff
     self._spam = value

  def get_spam(self):
     #do what you want/need before get the value
     return self._spam

  spam = property(get_spam, set_spam)

然后,每次调用swoosh.spam = spam_value都会调用set_spam方法,foo = swoosh.spam会调用get_spam方法。

答案 4 :(得分:1)

__init__()函数是您在首次创建对象时用于设置值的功能。

例如

class Swoosh:
    __init__(self, arg1, arg2, arg3):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3