我可以在不使用Python创建新类的情况下重写类函数吗



我正在pygame中制作一个游戏,我制作了一个"抽象"类,它的唯一工作是存储给定级别的精灵(目的是将这些级别对象放在列表中,以便于玩家从一个级别移动到另一个级别)

好吧,问题到此为止。如果我能在Python中做到这一点(Java的代码简洁):

Object object = new Object (){
    public void overriddenFunction(){
        //new functionality
        };
    };

当我在游戏中构建关卡时,我只需要用精灵的位置信息覆盖构造函数(或负责构建关卡的类/实例方法),因为为游戏中的每个关卡创建一个新的类并不是一个很好的答案。或者,我必须在级别类中创建方法,一旦级别对象被实例化,这些方法就会构建级别,并根据需要放置精灵。

因此,在一位更坚定的开发人员继续谈论这可能是多么反python之前(我已经读了足够多的关于这个网站的文章,从python专家那里得到了这种感觉),告诉我它是否可行。

是的,你可以!

class Foo:
    def do_other(self):
        print('other!')
    def do_foo(self):
        print('foo!')

def do_baz():
    print('baz!')
def do_bar(self):
    print('bar!')
# Class-wide impact
Foo.do_foo = do_bar
f = Foo()
g = Foo()
# Instance-wide impact
g.do_other = do_baz
f.do_foo()  # prints "bar!"
f.do_other()  # prints "other!"
g.do_foo()  # prints "bar!"
g.do_other()  # prints "baz!"

因此,在更多的stanch开发人员继续讨论这可能是如何反python的之前

以这种方式重写函数(如果你有充分的理由这样做的话)在我看来相当像蟒蛇。你可能必须这样做的一个原因/方式的例子是,如果你有一个动态特性,而静态继承没有或不能应用于它。

反对的案例可以在Python的禅宗中找到:

  • 美丽胜于丑陋
  • 可读性很重要
  • 如果实现很难解释,那就是个坏主意

是的,这是可行的。在这里,我使用functools.partial将隐含的self参数获取到一个正则(非类方法)函数中:

import functools
class WackyCount(object):
    "it's a counter, but it has one wacky method"
    def __init__(self, name, value):
        self.name = name
        self.value = value
    def __str__(self):
        return '%s = %d' % (self.name, self.value)
    def incr(self):
        self.value += 1
    def decr(self):
        self.value -= 1
    def wacky_incr(self):
        self.value += random.randint(5, 9)
# although x is a regular wacky counter...
x = WackyCount('spam', 1)
# it increments like crazy:
def spam_incr(self):
    self.value *= 2
x.incr = functools.partial(spam_incr, x)
print (x)
x.incr()
print (x)
x.incr()
print (x)
x.incr()
print (x)

和:

$ python2.7 wacky.py
spam = 1
spam = 2
spam = 4
spam = 8
$ python3.2 wacky.py    
spam = 1
spam = 2
spam = 4
spam = 8

编辑以添加注释:这是每个实例的覆盖。它利用了Python的属性查找序列:如果x是类K的实例,那么x.attrname从查找x的字典开始查找属性。如果未找到,则下一次查找在K中。所有的正规类函数实际上都是K.func。因此,如果您想动态替换函数,请使用@Brian Cane的答案。

我建议通过继承为每个级别使用不同的类。

但是,如果你真的像对待Java一样对待Python,那么你可能会从copy.deepcopy()和monkey补丁中获得一些好处。

最新更新