Python 创建带有大量导入函数的类
假设我在Python 创建带有大量导入函数的类,python,class,oop,object,encapsulation,Python,Class,Oop,Object,Encapsulation,假设我在alotoffunc.py中有很多函数,它们被一种以上的对象使用 假设ObjectI和ObjectI和ObjectXI都在alotoffunc.py中使用了一些函数。每个对象都使用不同的函数集,但所有对象都有变量Object.table alotoffunc.py: def abc(obj, x): return obj.table(x) * 2 def efg(obj, x): return obj.table(x) * obj.table(x) def hij(obj,
alotoffunc.py
中有很多函数,它们被一种以上的对象使用
假设ObjectI
和ObjectI
和ObjectXI
都在alotoffunc.py
中使用了一些函数。每个对象都使用不同的函数集,但所有对象都有变量Object.table
alotoffunc.py
:
def abc(obj, x):
return obj.table(x) * 2
def efg(obj, x):
return obj.table(x) * obj.table(x)
def hij(obj, x, y):
return obj.table(x) * obj.table(y)
def klm(obj, x, y):
return obj.table(x) *2 - obj.table(y)
然后我导入函数并重载它们:
import alotoffunc
class ObjectI:
def abc(self, x):
return alotoffunc.abc(self, x)
def efg(self, x):
return alotoffunc.efg(self, x)
class ObjectII:
def efg(self, x):
return alotoffunc.efg(self, x)
def klm(self, x, y):
return alotoffunc.klm(self, x, y)
class ObjectXI:
def abc(self, x):
return alotoffunc.abc(self, x)
def klm(self, x, y):
return alotoffunc.klm(self, x, y)
现在看起来像是一团糟,我应该如何构建我的对象类并安排我的alotoffunc.py
你可以做:
from alotoffunc import *
然后,例如,如果我们有变量o1
,o2
,它们是Object1
和Object2
的实例,我们可以:
abc(o1,x)
efg(o2,x)
...
它不像调用o1.abc(x)的OO方法那样“漂亮”,但它比重写所有方法更易于维护
“导入”*的功能是让您不必使用包名,如alotoffunc.abc
等等
编辑
正如@JamesKing所评论的,如果类中有同名函数,则此解决方案不起作用。因为它们看起来没用——它们只是调用导入的函数——我正在考虑删除它们。如果这不适用于您的代码,您应该像他所说的那样使用from\uuuuuuuuuuuuuuuuuuuuuuuuuuuas\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
。(1)您可以有一个实现所有方法的基类,然后覆盖不必要的方法,在子类中引发NotImplementedError
(2) 您可以使用mixin来减少重复:
import alotoffunc
class MixinAbc:
def abc(self, x):
return alotoffunc.abc(self, x)
class MixinEfg:
def efg(self, x):
return alotoffunc.efg(self, x)
class MixinKlm:
def klm(self, x, y):
return alotoffunc.klm(self, x, y)
class ObjectI(MixinAbc, MixinEfg):
pass
class ObjectII(MixinEfg, MixinKlm):
pass
class ObjectXI(MixinAbc, MixinKlm):
pass
您还可以将此方法与@cpburnz的方法相结合。最简单的方法是将所需函数作为实例方法直接绑定到其定义中的类。请注意,每个函数将接收self
作为第一个参数
import alotoffunc
class ObjectI:
abc = alotoffunc.abc
efg = alotoffunc.efg
class ObjectII:
efg = alotoffunc.efg
klm = alotoffunc.klm
class ObjectXI:
abc = alotoffunc.abc
klm = alotoffunc.klm
如果各种函数没有明确的逻辑分组,这可能是定义混合类的一种更简单的方法。分组确实取决于您的用例,因此混入方法可以更好地取决于具体情况。如果我想避免混入,也许为了最小化代码的不透明性,我会这样做:
class ObjectI:
from alotoffunc import abc, efg
class ObjectII:
from alotoffunc import efg, klm
class ObjectXI:
from alotoffunc import abc, klm
每当您创建类的实例时,导入的方法就会自动绑定。换句话说,默认情况下它们是实例方法
如果希望它们是静态方法,请按如下方式使用:
class ObjectI:
from alotoffunc import abc, efg
abc = staticmethod(abc)
另外,我也不会因为有这些多个导入语句而太担心性能问题,因为Python足够聪明,可以只运行一次导入的模块,然后将其保存在内存中,以备以后需要
如果要导入的函数具有某种逻辑分组,那么您肯定应该使用mixin,或者将函数组织到单独的“mixin模块”中,这样您甚至可以从mixinmodule import*
执行。对于mixin类方法,我认为常规import语句比from import更好,除非您的函数名很长,并且只想键入一次 这是一种“工厂”方法。如果你没有那么多的功能,可能会过于复杂,但如果你真的有“很多”,可能会成功
import alotoffunc
class Builder(object):
def __init__(self, objtype):
objtypes = { 'ObjectI': ['abc', 'efg'],
'ObjectII': ['efg', 'klm'],
'ObjectXI': ['abc', 'klm']}
for func in objtypes[objtype]:
self.__dict__[func] = getattr(alotoffunc, func)
这个怎么样:
import alotoffunc
import types
class ObjectI:
def __init__(self):
setattr(self, abc, types.MethodType(alotoffunc.abc, self))
setattr(self, efg, types.MethodType(alotoffunc.efg, self))
class ObjectII:
def __init__(self):
setattr(self, efg, types.MethodType(alotoffunc.efg, self))
setattr(self, klm, types.MethodType(alotoffunc.klm, self))
class ObjectXI:
# ...
(可能有一些缺陷或打字错误,但基本思想是正确的。我在代码中使用了类似的东西
这会在创建时将原始函数绑定到每个实例。setattr()不是必需的,但我更喜欢这样来表示发生了一些“魔法”
我很确定有更好的方法在类对象中创建方法,但这可能需要元类和/或更多的魔法。我认为实现目标的更干净的方法是使用python的多重继承功能。许多程序员讨厌MI,声称它产生混乱的代码或很难维护。只要你如果你在计划课程时很小心,那么使用MI会非常有帮助
SomeClasses.py——通常每个类都存储在单独的文件中
class ABCClass:
def abc(obj, x):
return obj.table(x) * 2
class DEFClass:
def efg(obj, x):
return obj.table(x) * obj.table(x)
class HIJClass:
def hij(obj, x, y):
return obj.table(x) * obj.table(y)
class KLMClass:
def klm(obj, x, y):
return obj.table(x) *2 - obj.table(y)
py——除非您确实需要重写基类的功能,否则不需要额外的代码
import SomeClasses #or each class file
class ObjectI (ABCClass, EFGClass):
pass
class ObjectII (EFGClass, KLMClass):
pass
class ObjectXI (ABCClass, KLMClass):
pass
当然,这是一个简单的例子,每个基类只有一个函数。一个真正的例子是当将图像打包到共享纹理资源时。您需要PIL.Image附带的功能,但能够将图像作为叶节点存储在自制的树数据结构中。您可以使用多重继承来使用最少的代码创建两个类的方法。LeafImage将拥有两个类的所有方法,并且当您决定修改TreeLeaf时,LeafImage中不需要额外的代码
class LeafImage (PIL.Image, TreeLeaf):
pass
在我看来,这并不是一团糟。如果这让你感到不安,你可以用一个实现所有方法的基类,然后重写不必要的基类,在子类中产生NotImplementedError
,或者将方法组合并到mixin中。我同意Selcuk的观点。你所做的看起来很合理。子类化可能会减少代码量稍微有点,但也可能会牺牲清晰度,因为你会覆盖你不想要的函数,而不是添加你想要的函数。mixin听起来不错,但控制多态性可能会让我以后头疼,在我使用mixin之后,有什么关于如何处理的提示吗?我不明白为什么你认为这看起来像一团乱麻,你能解释一下吗这有什么乱七八糟的呢?从C/Java的OOP角度来看,我应该创建一个类层次结构并适当地继承类。但是在python中,我不知道最好的方法是什么。这就是为什么我认为它非常乱七八糟,在开发时我可以保存一些重复的代码。仔细看一下类的名称与导入的函数的名称相同。可能这是真的,但看起来