调用属性的获取器、设置器、删除器 - Python

1 投票
3 回答
3400 浏览
提问于 2025-04-17 20:51

我在尝试调用一个叫做 fdel() 的方法时,遇到了错误:“类型错误:'locationTile' 不是一个可调用的对象”。代码如下:

class GamePlayLocationTiles(object):
    """The stuff needed for game play"""
    _locationTiles = []

    def locationTiles():
        doc = "property locationTiles's doc string"
        def fget(self):
            return self._locationTiles[0]
        def fset(self, value):
            self._locationTiles = value[0]
        def fdel(self):
            del self._locationTiles[0]
        return locals()  # credit: David Niergarth
    locationTiles = property(**locationTiles())

    def __init__(self):
        self.fill_location_tiles_list()

在不同的模块中:

import game_play_model

class GamePlayController:
    """perform operations on the game_play_model"""

    def __init__(self):
        self.the_game_location_tiles = game_play_model.GamePlayLocationTiles()
        self.shuffle_location_tiles()


    def shuffle_location_tiles(self):
        self.the_game_location_tiles.locationTiles().fdel() //this line causes the error

def main():
    the_game_play_controller = GamePlayController()

if __name__ == '__main__':
    main()

我只是想测试一下如何通过 getter、setter 和 deleter 来访问一个私有变量,结果出现了这个错误。

3 个回答

0
def locationTiles():
    doc = "property locationTiles's doc string"
    def fget(self):
        return self._locationTiles[0]
    def fset(self, value):
        self._locationTiles = value[0]
    def fdel(self):
        del self._locationTiles[0]
    return locals()  # credit: David Niergarth

locationTiles = property(**locationTiles()) # This redefines locationTiles to a variable
def shuffle_location_tiles(self):
    self.the_game_location_tiles.locationTiles().fdel() //this line causes the error

我注意到你有一个函数和一个变量,它们的名字是一样的。这可能会导致执行时出现问题。当你尝试调用函数locationTiles()时,Python会把它当作变量locationTiles来看待。

2

使用 property 的好处在于,你不是直接调用函数,而是通过常见的 Python 写法来获取、设置或删除属性。

举个例子,你不会直接写 self.the_game_location_tiles.locationTiles().fdel(),而是会写 del self.the_game_location_tiles.locationTiles,这样就会自动调用你的 fdel() 方法。

获取和设置属性也是一样的道理:

  • self.the_game_location_tiles.locationTiles 会使用你的 fget 方法。
  • self.the_game_location_tiles.locationTiles = y 会使用你的 fset 方法。
4

def shuffle_location_tiles(self):
    del self.the_game_location_tiles.locationTiles

fdel 这个函数不应该被直接调用。当你试图删除某个属性时,它会自动被调用。

举个例子,

class Foo(object):
    def x():
        def fget(self):
            """I'm the 'x' property."""
            return self._x

        def fset(self, value):
            self._x = value

        def fdel(self):
            print('deleting x')
            del self._x
        return locals()
    x = property(**x())

    def __init__(self):
        self._x = None


c = Foo()
del c.x
# deleting x

self.the_game_location_tiles.locationTiles() 会出现错误

"Type error: 'locationTile' is not a callable

因为 self.the_game_location_tiles.locationTiles 调用了 fget 并返回了一个值,self._locationTiles[0]。这个值恰好是不可调用的。

你可以通过 GamePlayLocationTiles.locationTiles 来访问这个属性,然后用

GamePlayLocationTiles.locationTiles.fdel(self.the_game_location_tiles)

来调用 fdel,但其实没有必要这样做,因为你可以直接使用这个语句

del self.the_game_location_tiles.locationTiles

撰写回答