Vielleicht habt ihr schon von DuckTyping gelesen. Für alle die es noch nicht getan haben:
Wenn es wie eine Ente läuft und es wie eine Quakt ist es eine Ente. Sprich wenn ein Object z.B. read,write und seek funktionen besitzt ist es ein Stream, es ist egal wovon die Klasse vererbt wurde.
Ich habe nun ein kleines Script erstellt dass DuckTyping "vereinfachen" soll
Hier mal das Script:
Code: Alles auswählen
import inspect
import types
class Function(object):
    """
    Arguments:
        name: Name der Funktion (string)
        numArgs: Anzahl der benötigten Parameter (integer)
        keywordArgs: Die KeywordArguments als Liste, ['arg1','arg2']
    """
    __slots__ = ['name','numArgs','keywordArgs']
    def __init__(self, name, numArgs, kwArgs=[]):
        self.name = name
        self.numArgs = numArgs
        self.keywordArgs = kwArgs
class Property(object):
    """
    Arguments:
        name: Name des Property (string)
        readable: Property hat fget Methode (boolean)
        writable: Property hat fset Methode (boolean)
        deletable: Property hat fdel Methode (boolean default=>False)
    """
    __slots__ = ['name','readable','writable','deletable']
    def __init__(self, name, readable, writable, deletable=False):
        self.name = name
        self.readable = readable
        self.writable = writable
        self.deletable = deletable
class Attribute(object):
    """
    Arguments:
        name: Name des Attributs
        type_: Typ des Attributs (muss vergleichbar mit type(attribut) sein)
    """
    __slots__ = ['name', 'type']
    def __init__(self, name, type_):
        self.name = name
        self.type = type_
def _checkFunction(obj, function):
    func = getattr(obj, function.name, None)
    if func:
        if type(func) in [types.BuiltinFunctionType,types.BuiltinMethodType]:
            return True
        
        try:
            func = func.im_func
        except AttributeError:
            pass
        try:
            args, varargs, varkw = inspect.getargs(func.func_code)
            defaults = func.func_defaults
        except AttributeError:
            return False
        
        if defaults == None:
            defaults = ()
        
        del args[0] # self loeschen
        
        if varargs and varkw:
            if len(args)-len(defaults) > function.numArgs:
                return False
        elif varargs:
            if len(args) > 0:
                for x in function.keywordArgs:
                    if not x in args:
                        return False
        elif varkw:
            if len(args)-len(defaults) > 0:
                for x in function.keywordArgs:
                    count = 0
                    for x in args:
                        if x in function.keywordArgs:
                            count += 1
                    if count != len(args)-len(defaults):
                        return False
                
        else:
            if not function.numArgs >= len(args)-len(defaults):
                return False
            if len(args) < function.numArgs:
                return False
        
        return True
    return False
def _checkProperty(obj, prop):
    cls = obj.__class__
    classprop = getattr(cls, prop.name, None)
    
    if classprop:
        if not isinstance(classprop, property):
            return False
        if prop.readable and not getattr(classprop, 'fget', None):
            return False
        if prop.writable and not getattr(classprop, 'fset', None):
            return False
        if prop.deletable and not getattr(classprop, 'fdel', None):
            return False
        return True
    return False
def _checkAttribute(obj, attr):
    attribute = getattr(obj, attr.name, None)
    if attribute:
        if type(attribute) != attr.type:
            return False
        return True
    return False
_attributeChoose = { Function: _checkFunction,
                    Property: _checkProperty,
                    Attribute: _checkAttribute}
def isDucky(obj, neededAttributes):
    for attr in neededAttributes:
        if not _attributeChoose[attr.__class__](obj, attr):
            return False
    return True
nun könnt ihr, wenn ihr eine Library oder Funktion für andere zur verfügung stellt einfach folgendes implementieren:
Code: Alles auswählen
import DuckTyping as dt
wantedObject = [
    dt.Function('check',2),
    dt.Attribute('count',int)
               ]
def meineFunktion(requiredObject):
    if dt.isDucky(requiredObject, wantedObject):
        print 'alles ok, ist ein kompatibles object'
    else:
        print 'leider stellt dieses objekt nicht alle attribute zur verfügung die wir brauchen'
Habs mal aus Interesse an DuckTyping geschrieben, in einem Projekt verwendet hab ich es noch nicht.
Gruss Rayo
