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

mal*_*ree 9 python

我有一个对象需要传递4-5个值.为了显示:

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

    [... methods ...]
Run Code Online (Sandbox Code Playgroud)

现在,使用方法Swoosh是:

swoosh = Swoosh()
swoosh.set_spam('Spam!')
swoosh.set_eggs('Eggs!')
swoosh.set_swallow('Swallow!')
swoosh.set_coconut('Migrated.')
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Dav*_*ebb 15

首先,您使用的是旧式课程.你真的应该使用继承自的新样式类object:

class Swoosh(object):
Run Code Online (Sandbox Code Playgroud)

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

def __init__(self,spam,eggs,swallow,coconut):
    self.spam = spam
    self.eggs = eggs
    self.swallow = swallow
    self.coconut = coconut
Run Code Online (Sandbox Code Playgroud)

这将允许您:

s = Swoosh('Spam!','Eggs','Swallow','Migrated')
Run Code Online (Sandbox Code Playgroud)

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

def __init__(self,spam,eggs,swallow,coconut='Migrated.'):
        self.spam = spam
        self.eggs = eggs
        self.swallow = swallow
        self.coconut = coconut
Run Code Online (Sandbox Code Playgroud)

如果要在设置属性时验证它们,则应使用标准property属性而不是创建自己的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
Run Code Online (Sandbox Code Playgroud)

注意:除非您使用如上所述的新式类,否则property无效.

在您的示例中,您有:

class Swoosh():
    spam = ''
    eggs = ''
    swallow = ''
    coconut = ''
Run Code Online (Sandbox Code Playgroud)

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

如果要为对象属性设置默认值,最好__init__不要像上面描述的那样为参数设置默认值,而不是使用class属性.


Lau*_*low 10

首先,这个:

class Swoosh():
    spam = ''
    eggs = ''
    swallow = ''
    coconut = ''
Run Code Online (Sandbox Code Playgroud)

然后设置属性spam,eggs等等.然后你的set_spam方法可以继续创建隐藏类属性的同名对象属性.换句话说,定义这些属性没有任何效果,只会混淆事物.

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

class Swoosh():
    def __init__(self, spam="", eggs="", swallow="", coconut=""):
        self.spam = spam
        self.eggs = eggs
        self.swallow = swallow
        self.coconut = coconut
Run Code Online (Sandbox Code Playgroud)

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

o1 = Swoosh(eggs="Eggs!", coconut="Carried by the husk")
Run Code Online (Sandbox Code Playgroud)

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

    def __init__(self, spam, eggs, swallow="", coconut=""):
Run Code Online (Sandbox Code Playgroud)

并且根本不使用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)
Run Code Online (Sandbox Code Playgroud)

通过以上更改,这个:

o2 = Swoosh(eggs="yes", spam="spam")
print o2.spam
Run Code Online (Sandbox Code Playgroud)

版画

spam spam spam spam spam
Run Code Online (Sandbox Code Playgroud)

注意:正如Dave Webb在他的回答中指出的那样object,除非你使用python 3.0+,否则你需要为要运行的属性创建子类,在这种情况下类隐式地进行子类化object.哦,不要跟随肖恩·维埃拉的链接到Python是不是Java的文章.这是必读的.


Sea*_*ira 6

可以通过覆盖类上适当的 get 和 set 方法(如果在所有情况下都需要进行验证)或通过使用内置更改特定属性来完成property基本验证。请记住,Python 不是 Java(当然,Java 也不是 Python)。

至于你想如何创建类,你有几种选择:

1) 使用__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
Run Code Online (Sandbox Code Playgroud)

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

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

您当前执行此操作的方式,每个实例Swoosh共享这些变量的相同值,并且更改spamon的值将为每个尚未设置具有相同名称的实例属性的实例Swoosh更改它(这可能不是)不是你想要的。)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
Run Code Online (Sandbox Code Playgroud)