Python decorate a class to change parent object type

柔情痞子 提交于 2019-12-04 12:13:49

Use 3-arguments type:

def makeSomeNicelyDecoratedSubclass(someclass):
  return type('MyNiceName', (someclass,), {'new_attribute':'something'})

This is indeed, as you surmised, a reasonably popular idiom.

Edit: in the general case if someclass has a custom metaclass you may need to extract and use it (with a 1-argument type) in lieu of type itself, to preserve it (this may be the case for your Django and App Engine models):

def makeSomeNicelyDecoratedSubclass(someclass):
  mcl = type(someclass)
  return mcl('MyNiceName', (someclass,), {'new_attribute':'something'})

This also works where the simpler version above does (since in simple cases w/no custom metaclasses type(someclass) is type).

Will McCutchen

Responding to your comments on voyager's answer:

from google.appengine.ext import db

class Mixin(object):
    """Mix in attributes shared by different types of models."""
    foo = 1
    bar = 2
    baz = 3

class Person(db.Model, Mixin):
    name = db.StringProperty()

class Dinosaur(db.polymodel.PolyModel, Mixin):
    height = db.IntegerProperty()

p = Person(name='Buck Armstrong, Dinosaur Hunter')
d = Dinosaur(height=5000)

print p.name, p.foo, p.bar, p.baz
print d.height, d.foo, d.bar, d.baz

Running that results in

Buck Armstrong, Dinosaur Hunter 1 2 3
5000 1 2 3

Is that not what you had in mind?

Why can't you use multiple inheritance?

class Origin:
  new_attribute = 'something'

class X:
  pass

class Y:
  pass

class X1(Origin, X):
  pass

class Y1(Origin, Y):
  pass
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!