我可以覆盖类函数而无需在Python中创建新类吗?

Mik*_*tte 6 python oop polymorphism overriding object

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

好吧,那么问题.如果我可以在Python中完成相同的操作(代码简洁的Java):

Object object = new Object (){
    public void overriddenFunction(){
        //new functionality
        };
    };
Run Code Online (Sandbox Code Playgroud)

当我在游戏中构建关卡时,我只需要覆盖构造函数(或者负责构建关卡的类/实例方法)以及关于精灵所在位置的信息,因为为每个级别创建一个新类游戏并不是那么优雅的答案.或者,我必须在级别类中创建方法,然后在实例化级别对象后构建级别,根据需要放置子级别.

所以,在一个更坚定的开发人员继续谈论这可能是什么样的反python之前(我已经阅读了足够多的网站以获得Python专家的热情),请告诉我它是否可行.

Bri*_*ain 5

是的你可以!

class Foo(object):
    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()
f.do_other()

g.do_foo()
g.do_other()
Run Code Online (Sandbox Code Playgroud)

所以,在更多的stanch开发人员继续谈论这可能是什么样的反python之前

以这种方式覆盖函数(如果你有充分的理由这样做)对我来说似乎是合理的pythonic.您可能必须执行此操作的一个原因/方式的示例是,如果您具有静态继承未应用或无法应用的动态功能.

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

  • 美丽胜过丑陋.
  • 可读性很重要.
  • 如果实施很难解释,这是一个坏主意.


tor*_*rek 5

是的,这是可行的。在这里,我使用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)
Run Code Online (Sandbox Code Playgroud)

和:

$ python2.7 wacky.py
spam = 1
spam = 2
spam = 4
spam = 8
$ python3.2 wacky.py    
spam = 1
spam = 2
spam = 4
spam = 8
Run Code Online (Sandbox Code Playgroud)

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