[TL; DR]感谢Alexi - 我有一个工作解决方案
我试图弄清楚Python类和继承,以便我可以创建一个协议解码器包。
包需要按如下方式工作:
我之前在C代码中完成了这项工作,使用共享对象,我尝试使用python创建类似的东西。
第1部分伪代码是这样的:
def GetDecoderViaId( idnumber ):
filename = "all_decoders/protocol_%04x.py" % idnumber
# Pseudo code use default if special is not found
if (! os.access(filename,os.R_OK)):
filename = "all_decoders/protocol_DEFAULT.py"
# Question #1 How do I do this
# Where each "filename" is a python class.
theclass = import_by_filename( filename )
return theclass
第2部分 - 解码器需要来自一个公共基类。我已经完成了简单的课程,但是当我尝试使用我通过谷歌找到的各种技术加载它们时,什么不起作用。我可以加载一些东西,我似乎无法调用解码器。
问题#2我该怎么做?
My Decoder Base Class如下所示:
# Simple base class
def DecoderBase(object):
def __init__(id,name,compatlist):
self.id = id
self.name = name
self.compatiblelist = compatlist
def Decode( bytes, byte0, byteN ):
""" Default is just a hex dump """
HexDump( bytes, byte0, byteN )
def GetName(self):
return self.name
def GetId(self):
return self.id
def IsCompatible(id):
return id in self.compatiblelist
以下是两个示例派生类,它们将位于单独的文件中。
# example: "all_decoders/protocol_1234.py"
class DogDecoder( DecoderBase ):
def __init__():
# pass important things to base constructor
super( DecoderBase, self ).__init__("dog","Snoopy", ["beagle", "peanuts" ])
def Decode( self, byte0, byteN ):
Snoopy specific code goes here
# Example: "all_decoders/protocol_4321.py"
class CatDecoder( DecoderBase ):
def __init__():
# pass important things to base constructor
super( DecoderBase, self ).__init__("cat","Garfield", ["fat-cat", "cartoon-cat" ])
def Decode( self, byte0, byteN ):
Garfield specific code goes here
有人能指出一些如何(1)如上所述加载模块的例子,(2)它们需要是派生类,(3)我如何称呼这些东西?
[注意:有些编辑,点击提交后注意到错别字]
答案 0 :(得分:2)
然而:
1a. a module's path is not ``foo/bar.py'`: it's `foo.bar`. So:
1aX first, drop the trailing `.py`
1aY then, change slashes into dots
both before passing the resulting string to
`importlib.import_module`
1b. when you import this way, you get a **module**, **not** a class!
I recommend you just name each class `Decoder` within its module
so you can just access it that way
1c. to make directory `foo` into a Python package, the directory
**must** contain a file `__init__.py` (which can be empty).
不需要从同一个基类派生每个Decoder
类;如果您想要它,为了您的方便,将基类放在例如foo/base.py
中,让每个特定的解码器模块以import .base
开头,并派生每个Decoder类来自base.DecoderBase
。
所以你的代码应该是这样的:
import importlib
def GetDecoderViaId( idnumber ):
filename = "all_decoders/protocol_%04x.py" % idnumber
# Pseudo code use default if special is not found
if (!os.access(filename, os.R_OK)):
filename = "all_decoders/protocol_DEFAULT.py"
module_path = filename[:-3].replace('/', '.')
themodule = importlib.import_module(module_path)
theclass = themodule.Decoder
return theclass
请记得有一个空的all_decoders/__init__.py
,all_decoders.base.py
定义class DecoderBase
,例如
# in file: "all_decoders/protocol_1234.py"
import .base
class Decoder( base.DecoderBase ):
def __init__():
# pass important things to base constructor
super( DecoderBase, self ).__init__("dog","Snoopy", ["beagle", "peanuts" ]
def Decode( self, byte0, byteN ):
Snoopy specific code goes here
# in file: "all_decoders/protocol_4321.py"
import .base
class Decoder( DecoderBase ):
def __init__():
# pass important things to base constructor
super( DecoderBase, self ).__init__("cat","Garfield", ["fat-cat", "cartoon-cat" ]
def Decode( self, byte0, byteN ):
Garfield specific code goes here
“如何调用”现在是微不足道的,例如在与GetDecoderViaId
相同的Python模块中...:
theclass = GetDecoderViaId(theid)
aninstance = theclass(whatever, init, args, are, needed)
decoded = aninstance.Decode(byte0, byteN)
答案 1 :(得分:0)
工作解决方案:Grazie非常Alexi
import importlib
def GetDecoder(name,xtra):
theclass = importlib.import_module( 'Decoders.' + name )
return theclass.Decoder(xtra)
sh = GetDecoder('snoopy', 'hockey');
sp = GetDecoder('snoopy', 'pilot');
g = GetDecoder('garfield', None );
print( "Snoopy Hocky says: %s" % sh.Decode( 3, 4 ) )
# This has an extra method
sh.Bark()
print( "SnoopyPilot says: %s" % sp.Decode( 5, 9 ) )
# And so does this one
sh.Bark()
print("Garfield says: %s " % g.Decode( 1,3 ))
# A different method
g.Purr()
#
# This file is empty
#
class DecoderBase(object):
def __init__( self, n, idval ):
self.name = n
self.idcode = idval
print( "Base created: %s %d " % (self.name, self.idcode));
def GetName(self):
return self.name
def GetId(self):
return self.idcode
def Decode(self,b0,bn):
msg = ("Decode from byte %d to %d" % (b0, bn ))
return msg
from base import DecoderBase
class Decoder( DecoderBase ):
def __init__( self, varient ):
self.costume = varient
super( Decoder, self ).__init__( "Snoopy-" + varient, 0x444f47 );
# Override the decoder
def Decode( self, b0, b1 ):
# but only if snoopy is playing hockey
if self.costume == 'hockey':
return ("Hockey decode: %d to %d" % (b0, b1))
else:
return super(Decoder,self).Decode( b0, b1 )
def Bark(self):
print "Barking(%s) ..." % self.costume
from base import DecoderBase
class Decoder( DecoderBase ):
def __init__(self, varient ):
# Unlike snoopy decoder, garfield does not have any varients
super( Decoder, self ).__init__( "Garfield", 0x434154 );
# Override the decoder
def Decode( self, b0, b1 ):
return ("Garfield lasagna %d to %d" % (b0, b1))
def Purr( self ):
print "Purring like a cat.."
<强> END 强>