[英]Python private inheritance? How to trick isinstance()?
Snippet of django core code: django核心代码片段:
class ForeignKey(RelatedField, Field):
...
def db_type(self, connection):
rel_field = self.rel.get_related_field()
if (isinstance(rel_field, AutoField) or
(not connection.features.related_fields_match_type and
isinstance(rel_field, (PositiveIntegerField,
PositiveSmallIntegerField)))):
return IntegerField().db_type(connection=connection)
return rel_field.db_type(connection=connection)
This code is very bad, because if I define a custom field which inherits from AutoField
, then my db_type method will be ignored. 此代码是非常糟糕的,因为如果我定义它从继承的自定义字段
AutoField
,那么我的db_type方法将被忽略。
What I would like to do is to hide the fact that my class is an instance of AutoField
. 我想做的是隐藏我的类是
AutoField
实例的事实。 In C++, I would do that by private inheritance. 在C ++中,我会通过私有继承来实现。
Is there any way to trick isinstance
to return False
or to hide inheritance? 有没有办法欺骗
isinstance
返回False
或隐藏继承?
Code of my cutom field: 我的cutom字段代码:
class MyAutoField(models.AutoField):
def __init__(self, length, *args, **kwargs):
self.length = length
super(MyAutoField, self).__init__(*args, **kwargs)
def db_type(self, connection):
if connection.vendor == 'oracle':
return 'NUMBER(%s,0)' % (self.length)
if connection.vendor == 'postgresql':
if self.length <= 4:
return 'smallint'
if self.length <= 9:
return 'integer'
return 'bigint'
return super(MyAutoField, self).db_type(connection)
So I have a way to do it, but its via "monkey patching." 所以我有办法做到这一点,但它通过“猴子补丁”。 You can't use
ABCMeta
because that requires you override your base class's metaclass. 您不能使用
ABCMeta
因为这需要您覆盖基类的元类。
You could "change" isinstance as follows. 您可以“更改”实例如下。 It is important that "patches" only gets imported once, and I would only do this if is no other way.
重要的是“补丁”只能导入一次,我只会这样做,如果没有别的办法。
patches.py patches.py
import django.models
import mymodel
import __builtin__
def _isinstance(instance, clz):
if clz is models.AutoField and isinstance_orig(instance, MyAutoField):
return False
return isinstance_orig(instance, clz)
__builtin__.isinstance_orig = __builtin__.isinstance
__builtin__.isinstance = _isinstance
Then your test program: 然后你的测试程序:
class MyAutoField(models.AutoField): pass
x = MyAutoField()
print(isinstance(x, models.AutoField))
print(isinstance(x, models.MyAutoField))
Introducing Abstract Base Classes: PEP-3119 . 介绍抽象基类: PEP-3119 。 Below is an abstract example...
以下是一个抽象的例子......
class ABCMeta(type):
def __instancecheck__(cls, inst):
"""Implement isinstance(inst, cls)."""
return any(cls.__subclasscheck__(c)
for c in {type(inst), inst.__class__})
def __subclasscheck__(cls, sub):
"""Implement issubclass(sub, cls)."""
candidates = cls.__dict__.get("__subclass__", set()) | {cls}
return any(c in candidates for c in sub.mro())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.