Python 模块组织、继承和@classmethods
我正在尝试编写一个类,它的工作方式有点像内置函数和我见过的其他一些“成熟的”Python东西。我的肾盂疗法教育有点参差不齐,我担心我把它搞混了 我想创建一个类,作为一种存储库,包含未处理文件(及其名称)的字典和已处理文件(及其名称)的字典。我想实现一些其他(子?)类来处理打开和处理文件之类的事情。文件处理类应该能够更新主类中的字典。我还希望能够直接调用各个子模块,而无需单独实例化所有内容,例如:Python 模块组织、继承和@classmethods,python,class,inheritance,Python,Class,Inheritance,我正在尝试编写一个类,它的工作方式有点像内置函数和我见过的其他一些“成熟的”Python东西。我的肾盂疗法教育有点参差不齐,我担心我把它搞混了 我想创建一个类,作为一种存储库,包含未处理文件(及其名称)的字典和已处理文件(及其名称)的字典。我想实现一些其他(子?)类来处理打开和处理文件之类的事情。文件处理类应该能够更新主类中的字典。我还希望能够直接调用各个子模块,而无需单独实例化所有内容,例如: import Pythia p = Pythia() p.FileManager.addFile("
import Pythia
p = Pythia()
p.FileManager.addFile("/path/to/some/file")
甚至
Pythia.FileManager.addFile("/path/to/some/file")
我一直在看@classmethod
和super
之类的东西,但我不能说我完全理解它。我也开始怀疑,我可能把整个继承链都倒过来了——我认为我的主类实际上应该是处理类和处理类的子类。我还想知道,作为一个软件包,这一切是否会更好,但这是一个单独的、非常可怕的问题
以下是我目前的代码:
#!/usr/bin/python
import re
import os
class Pythia(object):
def __init__(self):
self.raw_files = {}
self.parsed_files = {}
self.FileManger = FileManager()
def listf(self,fname,f):
if fname in self.raw_files.keys():
_isRaw = "raw"
elif fname in self.parsed_files.keys():
_isRaw = "parsed"
else:
return "Error: invalid file"
print "{} ({}):{}...".format(fname,_isRaw,f[:100])
def listRaw(self,n=None):
max = n or len(self.raw_files.items())
for item in self.raw_files.items()[:max]:
listf(item[0],item[1])
def listParsed(self,n=None):
max = n or len(self.parsed_files.items())
for item in self.parsed_files.items()[:max]:
listf(item[0],item[1])
class FileManager(Pythia):
def __init__(self):
pass
def addFile(self,f,name=None,recurse=True,*args):
if name:
fname = name
else:
fname = ".".join(os.path.basename(f).split(".")[:-1])
if os.path.exists(f):
if not os.path.isdir(f):
with open(f) as fil:
Pythia.raw_files[fname] = fil.read()
else:
print "{} seems to be a directory.".format(f)
if recurse == False:
return "Stopping..."
elif recurse == True:
print "Recursively navingating directory {}".format(f)
addFiles(dir,*args)
else:
recurse = raw_input("Recursively navigate through directory {}? (Y/n)".format(f))
if recurse[0].lower() == "n":
return "Stopping..."
else:
addFiles(dir,*args)
else:
print "Error: file or directory not found at {}".format(f)
def addFiles(self,directory=None,*args):
if directory:
self._recursivelyOpen(directory)
def argHandler(arg):
if isinstance(arg,str):
self._recursivelyOpen(arg)
elif isinstance(arg,tuple):
self.addFile(arg[0],arg[1])
else:
print "Warning: {} is not a valid argument...skipping..."
pass
for arg in args:
if not isinstance(arg,(str,dict)):
if len(arg) > 2:
for subArg in arg:
argHandler(subArg)
else:
argHandler(arg)
elif isinstance(arg,dict):
for item in arg.items():
argHandler(item)
else:
argHandler(arg)
def _recursivelyOpen(self,f):
if os.path.isdir(f):
l = [os.path.join(f,x) for x in os.listdir(f) if x[0] != "."]
for x in l:
_recursivelyOpen(x)
else:
addFile(f)
首先:遵循公司的指导方针。模块名称、变量名称和函数名称应为带下划线的小写字母;只有类名应该是CamelCase
。否则,遵循代码有点困难。:)
您在这里混淆了OO概念:您有一个包含子类实例的父类
FileManager
是否主要像Pythia
那样,经过一些修改或扩展?考虑到这两者只在一起工作,我想不会
我不太确定您最终希望它是什么样子,但我认为您根本不需要继承FileManager
可以是它自己的类,self.file\u manager
在Pythia
实例上可以是FileManager
的实例,然后Pythia
可以在必要时委托给它。这与您使用此代码的方式相差不远
构建独立的小部件,然后担心如何将它们相互插入
此外,还有一些bug和样式错误:
- 你调用
,但忘记了\u递归打开(x)
自身。
- 逗号后的单个空格
- 注意
作为变量名:它也是内置函数的名称max
- 如果有帮助,请避免类型检查(
)。当代码根据参数类型执行十几种不同的操作时,遵循代码就变得格外困难。具有非常清晰的参数类型,并在必要时创建接受不同参数的帮助器函数isinstance
- 您在
中有FileManager
,但是Pythia.raw_files[fname]
是一个类,并且它没有Pythia
属性raw_files
- 检查
是否为递归
,然后检查真
,然后。。。还有别的。什么时候有别的事?另外,您应该使用假
而不是is
来测试内置单例,如下所示=
import Pythia
p = Pythia()
p.file_manager.addFile("/path/to/some/file")
这样的类结构可以工作:
class FileManager(object):
def __init__(self, parent):
self.parent = parent
def addFile(self, file):
# Your code
self.parent.raw_files[file] = file
def addFiles(self, files)
# Your code
for file in files:
self.parent.raw_files[file] = file
class Pythia(object):
def __init__(self):
self.file_manager = FileManager(self)
然而,有很多选择。您应该首先编写一些客户机代码,以确定您需要什么,然后实现与之匹配的类/对象。我不打算在python中使用继承,因为pythons的duck类型并不需要继承
另外,如果希望在不实例化类的情况下调用方法,请使用staticmethod,而不是classmethod。例如:
class FileManager(object):
@staticmethod
def addFiles(files):
pass
如果您
导入Pytia
,那是一个模块,而不是一个类。所以你不能做Pythia()
。您可以在名为Pythia
的模块中有一个名为Pythia
的类,在这种情况下,您可以执行Pythia.Pythia()
。但是你最好通过调用模块pythia
(正如PEP8所建议的那样)来避免混淆。还有一件事:self.FileManger=FileManager()
是一个非常糟糕的主意。将一个类和该类的一个实例命名为同一事物肯定会导致混淆。(如果你按照Eevee的建议遵循PEP8,这甚至不会出现-文件管理器
是通用文件管理器
实例的合理名称。但是如果你不遵循,你需要一些其他的命名方式,比如苹果风格文件管理器
)+1,但你仍然没有注意到一个大问题:他正在做import Pythia
,然后是Pythia()
。我不确定他是在寻找Pytia的导入Pytia
来代替第一个还是Pytia.Pythia()
来代替第二个,你的建议会使区别变得明显,但他仍然需要以一种方式或另一种方式来解决。pff,他就是这样。我认为这只是假设,而不是他尝试运行的实际代码。是的,他说这是他希望能够运行的代码。如果你读到这段话,他似乎在进一步混淆模块和类(例如,将FileManager
称为子模块),然后试图修补/修改一些东西,却不清楚自己在做什么……我尽量不立即跑到StackOverflow,以免被那些真正知道发生了什么的人弄得面红耳赤。我也应该承认,我没有达到我的政治公众人物标准……我被教导说,camelCase/下划线的区别是个人风格的问题。谢谢你的提醒。这里有一个秘密:我们并不总是知道发生了什么:)十次中有九次,一次