Python:简化继承器方法

Python:简化继承器方法,python,class,inheritance,subclass,factory,Python,Class,Inheritance,Subclass,Factory,我有这样的代码: class Base: def do( self ): self._member1 = 0 self._member2 = 1 class Derived1(Base): def do(self): Base.do(self) self._member3 = 0 self._member4 = 1 class Derived2(Base): def do(self): Base.do(self) self.

我有这样的代码:

class Base:
  def do( self ):
    self._member1 = 0
    self._member2 = 1

class Derived1(Base):
  def do(self):
    Base.do(self)
    self._member3 = 0
    self._member4 = 1

class Derived2(Base):
  def do(self):
    Base.do(self)
    self._member3 = 2
    self._member4 = 3

class Derived3(Base):
  def do(self):
    Base.do(self)
    self._member3 = 9
    self._member4 = 3
等等。以下是我所做的:

class Base(object):
  '''Base class.'''
  def do(self):
    self._member1 = 0
    self._member2 = 1

class Derived1(Base): pass
class Derived2(Base): pass
class Derived3(Base): pass
class Derived4(Base): pass

class DerivedFactory(object):
  '''Factory to create derived classes.'''
  members = \
  {
    1: (Derived1, 0, 1),
    2: (Derived2, 4, 5),
    3: (Derived3, 6, 7),
    4: (Derived4, 8, 9),
  }

  def do(self, key=1):
    derived = self.members[key][0]()
    derived.do() # Perform method from Base
    derived._member3 = self.members[key][1]
    derived._member4 = self.members[key][2]
    print(derived)
    print('\t%s' % derived.__dict__)

if __name__ == '__main__':
  factory = DerivedFactory()
  for key in range(1, 5):
    derived = factory.do(key)

然而,它并不像你看到的那样完美。我需要声明Derived1、Derived2等等。它似乎过于复杂了。你对如何导入这段代码有什么想法吗?谢谢

据我所知,您只是对减少重复代码感兴趣,这里有一个选项相当于您的顶级代码:

class Base:
    def do( self ):
        self._member1 = 0
        self._member2 = 1

def make_do(a, b):
    def do(self):
        Base.do(self)
        self._member3 = a
        self._member4 = b
    return do

class Derived1(Base):
    do = make_do(0, 1)

class Derived2(Base):
    do = make_do(2, 3)

class Derived3(Base):
    do = make_do(9, 3)
Oren在评论中建议的较短版本(请注意,要使其起作用,
Base
需要是一个新样式的类):

这是一个装饰版本,因为它是在评论中要求的:

class Base(object):
    def do( self ):
        self._member1 = 0
        self._member2 = 1

def add_do(a, b):
    def do(self):
        Base.do(self)
        self._member3 = a
        self._member4 = b
    def deco(cls):
        return type(cls.__name__, (Base,), {'do': do})
    return deco

@add_do(0, 1)
class Derived1(Base): pass

@add_do(2, 3)
class Derived2(Base): pass

@add_do(9, 3)
class Derived3(Base): pass
另一个decorator版本,它重写子类“
do
,而不是创建新类型(它还允许您使用旧样式的类):


据我所知,您只是对减少重复代码感兴趣,这里有一个选项相当于您的顶级代码:

class Base:
    def do( self ):
        self._member1 = 0
        self._member2 = 1

def make_do(a, b):
    def do(self):
        Base.do(self)
        self._member3 = a
        self._member4 = b
    return do

class Derived1(Base):
    do = make_do(0, 1)

class Derived2(Base):
    do = make_do(2, 3)

class Derived3(Base):
    do = make_do(9, 3)
Oren在评论中建议的较短版本(请注意,要使其起作用,
Base
需要是一个新样式的类):

这是一个装饰版本,因为它是在评论中要求的:

class Base(object):
    def do( self ):
        self._member1 = 0
        self._member2 = 1

def add_do(a, b):
    def do(self):
        Base.do(self)
        self._member3 = a
        self._member4 = b
    def deco(cls):
        return type(cls.__name__, (Base,), {'do': do})
    return deco

@add_do(0, 1)
class Derived1(Base): pass

@add_do(2, 3)
class Derived2(Base): pass

@add_do(9, 3)
class Derived3(Base): pass
另一个decorator版本,它重写子类“
do
,而不是创建新类型(它还允许您使用旧样式的类):


如果您只是使用类作为数据容器,并使用对数据进行操作的方法,则最好使用不同的模式:

from collections import namedtuple

Base = namedtuple("Base", ["member1", "member2"])
Derived = namedtuple("Derived", Base._fields + ("member3", "member4"))

def do(base_or_derived):

    print "Member1:", base_or_derived.member1
    print "Member2:", base_or_derived.member2

    if not isinstance(base_or_derived, Base):
        print "Member3:", base_or_derived.member3
        print "Member4:", base_or_derived.member4

if __name__ == "__main__":
    base = Base(0, 1)
    derived1 = Derived(0, 1, 0, 1)
    derived2 = Derived(0, 1, 2, 3)
    derived3 = Derived(0, 1, 9, 3)

    for item in [base, derived1, derived2, derived3]:
        do(item)

如果您只是使用类作为数据容器,并使用对数据进行操作的方法,则最好使用不同的模式:

from collections import namedtuple

Base = namedtuple("Base", ["member1", "member2"])
Derived = namedtuple("Derived", Base._fields + ("member3", "member4"))

def do(base_or_derived):

    print "Member1:", base_or_derived.member1
    print "Member2:", base_or_derived.member2

    if not isinstance(base_or_derived, Base):
        print "Member3:", base_or_derived.member3
        print "Member4:", base_or_derived.member4

if __name__ == "__main__":
    base = Base(0, 1)
    derived1 = Derived(0, 1, 0, 1)
    derived2 = Derived(0, 1, 2, 3)
    derived3 = Derived(0, 1, 9, 3)

    for item in [base, derived1, derived2, derived3]:
        do(item)

您还可以使用
type
函数动态创建类:def make_-derived(name,a,b):type(name,(Base,),{'do':make_-do(a,b)})Derived1=make_-derived('Derived1',0,1)Derived2=make_-derived('Derived2',2,3)Derived3=make_-derived('Derived3',9,3)好的建议,添加到我的答案中。@Oren确实,它被称为:)在我的答案中添加了一个带有装饰器的版本(不使用元类)。在最后一种情况下,值得一提的是,类装饰器将忽略原始类下的任何其他定义(如果编写了任何其他内容而不是
过程
)您还可以使用
type
函数动态创建类:def make_-derived(name,a,b):type(name,(Base,),{'do':make_-do(a,b)})Derived1=make_-derived('Derived1',0,1)Derived2=make_-derived('Derived2',2,3)Derived3=make_-derived('Derived3',9,3)好的建议,添加到我的答案中。@Oren确实,它的名称是:)在我的答案中添加了一个带有修饰符的版本(不使用元类)。在最后一个例子中,值得一提的是,类修饰符将忽略原始类下的任何其他定义(如果编写了任何其他定义而不是
pass
)否,成员只能在
do
方法中初始化。否,只能在
do
方法中初始化成员。