假设我有一个多继承场景:
class A(object):
# code for A here
class B(object):
# code for B here
class C(A, B):
def __init__(self):
# What's the right code to write here to ensure
# A.__init__ and B.__init__ get called?
Run Code Online (Sandbox Code Playgroud)
有写作两种典型的方法C的__init__:
ParentClass.__init__(self)super(DerivedClass, self).__init__()但是,在任何一种情况下,如果父类(A和B)不遵循相同的约定,则代码将无法正常工作(某些可能会被遗漏,或被多次调用).
那么又是什么样的正确方法呢?很容易说"只是保持一致,遵循一个或另一个",但如果A或B来自第三方图书馆,那么呢?有没有一种方法可以确保所有父类构造函数被调用(并且以正确的顺序,只有一次)?
编辑:看看我的意思,如果我这样做:
class A(object):
def __init__(self):
print("Entering A")
super(A, self).__init__()
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super(B, self).__init__()
print("Leaving B")
class …Run Code Online (Sandbox Code Playgroud) Python 2.x有两种方法可以重载比较运算符,__cmp__或者"丰富的比较运算符",如__lt__. 丰富的比较超载被认为是首选,但为什么会这样呢?
丰富的比较运算符更容易实现每个,但您必须使用几乎相同的逻辑实现其中几个.但是,如果你可以使用内置cmp和元组排序,那么__cmp__变得非常简单并完成所有的比较:
class A(object):
def __init__(self, name, age, other):
self.name = name
self.age = age
self.other = other
def __cmp__(self, other):
assert isinstance(other, A) # assumption for this example
return cmp((self.name, self.age, self.other),
(other.name, other.age, other.other))
Run Code Online (Sandbox Code Playgroud)
这种简单性似乎比重载所有6(!)丰富的比较更好地满足了我的需求.(但是,如果你依赖于"交换的论证"/反映的行为,你可以把它归结为"只是"4,但这导致并发症的净增加,在我的拙见中.)
如果我只是超载,是否有任何不可预见的陷阱需要注意__cmp__?
我明白了<,<=,==等运营商也可以被重载用于其他目的,并且可以返回任何他们喜欢的对象.我不是在询问这种方法的优点,而是仅仅考虑使用这些运算符进行比较时的差异,这与它们对数字的意义相同.
更新:克里斯托弗指出,cmp正在消失3.x. 有没有其他方法可以使实施比较变得如上所述__cmp__?
这是一个关于Python Mixins的问题,一般来说可能很有用.我只是使用Django模型,因为这是我最熟悉的用例.
如果mixin继承自该类,它是否设计为与'object'混合使用?
代码示例,更正确或更好,或更好,取决于您想要实现的目标?
这个
class TaggingMixin(models.Model):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(models.Model, TaggingMixin):
title = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)
或这个:
class TaggingMixin(object):
tag = models.ForeignKey(Tag)
class Meta:
abstract = True
class MyModel(models.Model, TaggingMixin):
title = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)
我认为从对象继承是正确的方法.但我正在网上看到第一个案例的例子......
编辑:我已将我的后续问题转移到一个单独的问题:Django抽象模型与简单Python混合与Python ABCs
Python 3.4引入了一个新模块enum,它为该语言添加了枚举类型.该文档enum.Enum提供了一个示例来演示如何扩展它:
>>> class Planet(Enum):
... MERCURY = (3.303e+23, 2.4397e6)
... VENUS = (4.869e+24, 6.0518e6)
... EARTH = (5.976e+24, 6.37814e6)
... MARS = (6.421e+23, 3.3972e6)
... JUPITER = (1.9e+27, 7.1492e7)
... SATURN = (5.688e+26, 6.0268e7)
... URANUS = (8.686e+25, 2.5559e7)
... NEPTUNE = (1.024e+26, 2.4746e7)
... def __init__(self, mass, radius):
... self.mass = mass # in kilograms
... self.radius = radius # in meters
... @property
... def surface_gravity(self):
... # universal …Run Code Online (Sandbox Code Playgroud) 我需要扩展Networkx python包并Graph为我的特殊需要添加一些方法
我想这样做的方法是简单地推导出一个新类说NewGraph,并添加所需的方法.
然而,networkx中还有一些其他函数可以创建和返回Graph对象(例如,生成随机图).我现在需要将这些Graph对象转换为NewGraph对象,以便我可以使用我的新方法.
这样做的最佳方式是什么?或者我应该以完全不同的方式解决问题?
接口+扩展方法(mixin)是否优于抽象类?
如果你的答案是"它取决于",它依赖于什么?
我看到接口+扩展方法有两个可能的优点.
我还没有想到这种方法的缺点.接口+扩展方法失败可能有一个明显的简单原因.
关于这个主题的两篇有用的文章是
如果我有两个类,并且其中一个类具有我想在其他类中使用的函数,那么我使用什么以便我不必重写我的函数?
我有一个抽象的基类作为接口.
我有两个派生类的"集合",它们实现了抽象类的一半.(一个"set"定义与初始化相关的抽象虚拟方法,另一个"set"定义与实际"工作"相关的那些.)
然后,我得到了使用多继承来构造完全定义的类的派生类(并且本身不添加任何东西).
所以:(坏伪代码)
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
Run Code Online (Sandbox Code Playgroud)
首先,我可以这样做吗?我可以继承两个派生自同一Base的类吗?(希望如此).
虽然这是"真正的问题"(我在上面撒谎以简化示例).
我真正做的是将非抽象访问器方法添加到基类:
class AbsBase {
public:
void init() { init_impl(); }
void work() { …Run Code Online (Sandbox Code Playgroud) 以下肯定有效,但非常繁琐:
T(const T&) = delete;
T(T&&) = delete;
T& operator=(const T&) = delete;
T& operator=(T&&) = delete;
Run Code Online (Sandbox Code Playgroud)
我正试图发现最简洁的方式.以下工作会吗?
T& operator=(T) = delete;
Run Code Online (Sandbox Code Playgroud)
更新
请注意,我选择T& operator=(T)而不是T& operator=(const T&)或T& operator=(T&&),因为它可以同时满足两个目的.
我看到sklearn 文档中提到了Transformer和estimator。
这两个词有什么区别吗?
python ×6
inheritance ×3
c++ ×2
.net ×1
base-class ×1
c++11 ×1
class ×1
constants ×1
copy ×1
enums ×1
interface ×1
methods ×1
oop ×1
python-3.x ×1
scikit-learn ×1
super ×1