Python 类的 getter 和 setter 静态方法及类方法

-1 投票
1 回答
2495 浏览
提问于 2025-04-18 15:36
class Spam(object): 
#a_string = 'candy'
def __init__(self, sold=0, cost=0): 
    self.sold = sold
    self.cost = cost
@staticmethod
def total_cost():
    return True

@classmethod
def items_sold(cls, how_many):

@property
def silly_walk(self):
    return print (self.a_string)

@silly_walk.setter
def silly_walk(self, new_string):
    self.a_string = new_string.upper()

def do_cost(self):
    if self.total_cost():
        print('Total cost is:', self.cost)

.

  from spam import Spam

def main ():
    cost = 25
    sold = 100
    a_string = 'sweets'
    sp = Spam(100, 25)
    sp.do_cost()
    sw = Spam.silly_walk(a_string)
    sw.silly_walk()

if __name__ == '__main__':
    main()

我刚开始学Python,不太明白怎么用设置器和获取器。我的目标是:

用@property来为一个叫silly_walk的属性创建设置器和获取器。设置器要把silly_walk字符串变成大写。

展示一些示例代码,说明如何访问这个静态方法。

展示一些示例代码,说明如何使用silly_walk的设置器和获取器。

我对类里面的“self”有点困惑,不太确定我做的是否正确。

更新:问题出在@classmethod没有返回值和缩进错误,现在一切都解决了,谢谢大家。

1 个回答

0

self 是一种约定。在类里面,你不是在写函数,而是在写方法。方法需要一个指向调用它的对象的引用作为第一个参数,按照约定,这个参数叫做 self。其实你可以把它叫成任何名字。

class Foo(object):
    def __init__(itsa_me_maaaario, name):
        itsa_me_maaario.name = "Mario"

这样也完全可以。

至于你代码的其他部分——你想问什么呢?看起来你的设置方法有点奇怪,不过除此之外,其他部分应该大致没问题。这样写会更好:

class Spam(object): # inherit from object in py2 for new-style classes
    def __init__(self, a_string, sold=0, cost=0) # put the positional arg first
        ...
    @staticmethod
    def total_cost():
        # you have to do something meaningful here. A static method can't access
        # any of the objects attributes, it's really only included for grouping
        # related functions to their classes.
    @classmethod
    def items_sold(cls, how_many):
        # the first argument to a classmethod is the class, not the object, so
        # by convention name it cls. Again this should be something relevant to
        # the class not to the object.
    @property
    def silly_walk(self):
        return self.a_string
        # don't call itself.
    @silly_walk.setter
    def silly_walk(self, new_string):
        self.a_string = new_string
        # it really just hides the attribute.

举个例子,我有一个类是用来抽象我负责的计算机系统的。可能是这样的:

class System(object):
    type_ = "Base system"
    def __init__(self, sitenum, devicenum, IP):
        self._sitenum = sitenum
        self._devicenum = devicenum
        self._IP = IP
        # the leading underscores are a flag to future coders that these are
        # "private" variables. Nothing stopping someone from using it anyway,
        # because System()._IP is still that attribute, but it makes it clear
        # that they're not supposed to be used that way.
    @staticmethod
    def ping_system(IP):
        subprocess.call(["ping",IP], shell=True) # OH GOD SECURITY FLAW HERE
        # group this with Systems because maybe that's how I want it? It's an
        # aesthetic choice. Note that this pings ANY system and requires an
        # argument of an IP address!
    @classmethod
    def type_of_system(cls):
        return cls.type_
        # imagine I had a bunch of objects that inherited from System, each w/
        # a different type_, but they all inherit this....
    @property
    def description(self):
        return "Site {}, Device {} @ {}".format(self._sitenum,
                                                self._devicenum,
                                                self._IP)
    @description.setter
    def description(self, *args):
        if len(args) == 3:
            self._sitenum, self._devicenum, self._IP = args
        elif len(args) == 1 and len(args[0]) == 3:
            self._sitenum, self._devicenum, self._IP = args[0]
        else:
            raise ValueError("Redefine description as Sitenum, Devicenum, IP")

示例:

computer = System(1, 1, '192.168.100.101')
System.ping_system('192.160.100.101') # works
computer.type_of_system # "Base system"
computer.description # "Site 1, Device 1 @ 192.168.100.101"
new_description = [1, 2, '192.168.100.102']
computer.description = new_description
# invokes description.setter
computer._devicenum # is 2 after the setter does its magic.

撰写回答