[英]Is there a benefit to defining a class inside another class in Python?
我在这里谈论的是嵌套类。 本质上,我有两个正在建模的类。 一个 DownloadManager 类和一个 DownloadThread 类。 这里明显的 OOP 概念是组合。 然而,组合并不一定意味着嵌套,对吧?
我有看起来像这样的代码:
class DownloadThread:
def foo(self):
pass
class DownloadManager():
def __init__(self):
dwld_threads = []
def create_new_thread():
dwld_threads.append(DownloadThread())
但现在我想知道是否存在嵌套会更好的情况。 就像是:
class DownloadManager():
class DownloadThread:
def foo(self):
pass
def __init__(self):
dwld_threads = []
def create_new_thread():
dwld_threads.append(DownloadManager.DownloadThread())
当“内部”类是一次性的时,您可能想要这样做,它永远不会在外部类的定义之外使用。 例如使用元类,有时这样做很方便
class Foo(object):
class __metaclass__(type):
....
如果您只使用一次,而不是单独定义元类。
我唯一一次使用这样的嵌套类时,我仅将外部类用作命名空间,将一堆密切相关的类组合在一起:
class Group(object):
class cls1(object):
...
class cls2(object):
...
然后从另一个模块中,您可以导入 Group 并将它们称为 Group.cls1、Group.cls2 等。然而,有人可能会争辩说,您可以通过使用一个模块来完成完全相同的工作(也许以一种不那么令人困惑的方式)。
我不懂 Python,但你的问题似乎很笼统。 如果它特定于 Python,请忽略我。
类嵌套是关于范围的。 如果您认为一个类仅在另一个类的上下文中才有意义,那么前者可能是成为嵌套类的好选择。
这是一种常见的模式,使辅助类成为私有的嵌套类。
嵌套类还有另一种用法,当人们想要构造其增强功能封装在特定嵌套类中的继承类时。
看这个例子:
class foo:
class bar:
... # functionalities of a specific sub-feature of foo
def __init__(self):
self.a = self.bar()
...
... # other features of foo
class foo2(foo):
class bar(foo.bar):
... # enhanced functionalities for this specific feature
def __init__(self):
foo.__init__(self)
注意,在的构造foo
,行self.a = self.bar()
将构造一个foo.bar
被构造的物体时实际上是一个foo
对象和foo2.bar
当要构造的对象对象实际上是一foo2
对象。
如果类bar
是在类foo
之外定义的,以及它的继承版本(例如,将称为bar2
),那么定义新类foo2
会痛苦得多,因为foo2
的构造foo2
需要有它的第一行替换为self.a = bar2()
,这意味着重写整个构造函数。
您可以使用类作为类生成器。 喜欢(在一些袖口代码中:)
class gen(object):
class base_1(object): pass
...
class base_n(object): pass
def __init__(self, ...):
...
def mk_cls(self, ..., type):
'''makes a class based on the type passed in, the current state of
the class, and the other inputs to the method'''
我觉得当你需要这个功能时,你会很清楚。 如果您不需要做类似的事情,那么它可能不是一个好的用例。
这样做真的没有任何好处,除非您正在处理元类。
班级:套房真的不是你想象的那样。 这是一个奇怪的范围,它会做一些奇怪的事情。 真的连课都没有! 它只是收集一些变量的一种方式——类的名称、基类、属性的小字典和元类。
名称、字典和基数都传递给作为元类的函数,然后将其分配给 class:suite 所在作用域中的变量“name”。
你可以通过弄乱元类获得什么,实际上是通过在你的标准类中嵌套类,更难阅读代码,更难理解代码,以及在不非常熟悉为什么“类”的情况下很难理解的奇怪错误作用域与任何其他 Python 作用域完全不同。
不,构图并不意味着嵌套。 如果要在外部类的命名空间中更多地隐藏它,那么有一个嵌套类是有意义的。
无论如何,我认为在你的情况下没有任何实际的嵌套用法。 这将使代码更难以阅读(理解),并且它还会增加缩进,这会使行更短并且更容易分裂。
无论哪种方式,在类内部或外部定义,都可以。 这是一个员工工资计划程序,其中帮助类 EmpInit 嵌入在类 Employee 中:
class Employee:
def level(self, j):
return j * 5E3
def __init__(self, name, deg, yrs):
self.name = name
self.deg = deg
self.yrs = yrs
self.empInit = Employee.EmpInit(self.deg, self.level)
self.base = Employee.EmpInit(self.deg, self.level).pay
def pay(self):
if self.deg in self.base:
return self.base[self.deg]() + self.level(self.yrs)
print(f"Degree {self.deg} is not in the database {self.base.keys()}")
return 0
class EmpInit:
def __init__(self, deg, level):
self.level = level
self.j = deg
self.pay = {1: self.t1, 2: self.t2, 3: self.t3}
def t1(self): return self.level(1*self.j)
def t2(self): return self.level(2*self.j)
def t3(self): return self.level(3*self.j)
if __name__ == '__main__':
for loop in range(10):
lst = [item for item in input(f"Enter name, degree and years : ").split(' ')]
e1 = Employee(lst[0], int(lst[1]), int(lst[2]))
print(f'Employee {e1.name} with degree {e1.deg} and years {e1.yrs} is making {e1.pay()} dollars')
print("EmpInit deg {0}\nlevel {1}\npay[deg]: {2}".format(e1.empInit.j, e1.empInit.level, e1.base[e1.empInit.j]))
要在外部定义它,只需取消缩进 EmpInit 并将 Employee.EmpInit() 更改为简单的 EmpInit() 作为常规的“has-a”组合。 但是,由于 Employee 是 EmpInit 的控制器并且用户不直接实例化或与之交互,因此在内部定义它是有意义的,因为它不是一个独立的类。 另请注意,实例方法 level() 旨在在此处的两个类中调用。 因此,它也可以方便地定义为 Employee 中的静态方法,这样我们就不需要将它传递给 EmpInit,而只需使用 Employee.level() 调用它。
此功能的一个很好的用例是错误/异常处理,例如:
class DownloadManager(object):
class DowndloadException(Exception):
pass
def download(self):
...
现在阅读代码的人知道与这个类相关的所有可能的异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.