sku*_*led 9 python inheritance metaclass
代码如下,只是基本结构:
class FooType(type):
def __new__( cls, name, bases, classdict ):
instance = type.__new__( cls, name, bases, classdict )
# What can I do here?
return instance
class FooBase( object, metaclass=FooType ):
def __init__( self ):
pass
class Foo( FooBase ):
def __init__( self, name ):
self.name = name
def method1( self ):
pass
def method2( self ):
pass
def specialmethod( self ):
pass
class A( Foo ):
pass
class B( Foo ):
pass
class C( Foo ):
_disallowed_methods = ['specialmethod']
Run Code Online (Sandbox Code Playgroud)
我想要做的是类的实例C不应该有specialmethod,但该方法应该可用于实例A和B.
我可以在类中重写此方法C并引发错误,但我不想这样做.
我意识到我可以在该检查的基础上添加代码来检查是否_disallowed_methods在输出中有任何一个.但我似乎无法从删除方法的使用到目前为止,我还没有尝试过任何方法.我试过的方法是,和.FooTypeinstancedir(instance)__dict__Cdelattr(instance, 'specialmethod')del instance.__dict__['specialmethod']
该delattr方法导致"AttributeError:specialmethod",并且该del方法导致"TypeError:'dict_proxy'对象不支持项删除"
基本上许多不同的类将继承Foo,但是其中一些不C应该具有specialmethod可用的特定方法,就像它们不可用的那样.
我究竟做错了什么?或者我怎么能做到这一点?
如果您有一个不想被修改的父级,以及一个具有一个或多个您希望无法访问的继承方法的子级,则可以使用描述符来实现。最简单的方法之一是使用property内置:
class Parent:
def good_method(self):
print('Good one')
def bad_method(self):
print('Bad one')
class Child(Parent):
bad_method = property(doc='(!) Disallowed inherited')
one = Parent()
one.good_method() # > 'Good one'
one.bad_method() # > 'Bad one'
two = Child()
two.good_method() # > 'Good one'
two.bad_method() # > AttributeError: unreadable attribute
two.bad_method # > AttributeError: unreadable attribute
two.bad_method = 'Test' # > AttributeError: can't set attribute
Run Code Online (Sandbox Code Playgroud)
帮助(两个)如何打印它:
Run Code Online (Sandbox Code Playgroud)class Child(Parent) | Method resolution order: | Child | Parent | builtins.object | | Data descriptors defined here: | | bad_method | (!) Disallowed inherited | | ---------------------------------------------------------------------- | Methods inherited from Parent: | | good_method(self) | | ---------------------------------------------------------------------- | Data descriptors inherited from Parent: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)
相当不错,在我看来。但是你应该小心,如果其他方法依赖它们,你应该小心不要以这种方式定义继承的方法(这可以通过使用代理类来避免,代理类从父类继承并重新定义这些方法以使用super().bad_method()而不是仅仅使用self.bad_method()并将其bad_method自身指向不允许使用的描述符)。如果需要,您可以编写更复杂的描述符逻辑
好吧,你不能以这种方式实现这一点,因为你必须修改不是C类,而是修改Foo真正包含的类specialmethod.但实际上你不能这样做,因为class是全局可变对象,任何更改Foo都会影响所有子类.
试着以另一种方式思考.例如,您可以修改访问C类属性的逻辑:
class C( Foo ):
def __getattribute__(self, name):
if name in ['specialmethod']:
raise AttributeError('no such method')
return super(C, self).__getattribute__(name)
Run Code Online (Sandbox Code Playgroud)
之后C('a').specialmethod()产生追溯:
Traceback (most recent call last):
File "meta.py", line 37, in <module>
C('a').specialmethod()
File "meta.py", line 34, in __getattribute__
raise AttributeError('no such method')
AttributeError: no such method
Run Code Online (Sandbox Code Playgroud)