Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 创建带有大量导入函数的类_Python_Class_Oop_Object_Encapsulation - Fatal编程技术网

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中,我不知道最好的方法是什么。这就是为什么我认为它非常乱七八糟,在开发时我可以保存一些重复的代码。仔细看一下类的名称与导入的函数的名称相同。可能这是真的,但看起来