Python:方法 X 实例 class A 并调用方法 E。当此 class 被实例化时,它再次调用方法 X。怎么解决好呢?

Python: Method X instances class A and calls method E. When this class is instanced it calls method X again. How to solve it in a good way?

嗯,整个问题都在问题标题中描述了。正如你们所看到的,我在打电话时遇到了这个问题。

顺便说一句,考虑到我已经导入了所有需要的库和 classes。

检查下面我的代码:

class PyUtility(object):

    #@Arguments:
        #path = file path to be opened 
        #op = mode in which the file will be opened, r+ by default
    #Return: A file for writing or reading, depending on the value of op variable
    def loadPath(self, path, op='r+'):
        print 'loadPath()'
        try:
            #In case the path string is '/example/example', instead of 'example/example'
            if path[0] == '/':
                path = path.lstrip('/')
            return open(path, op)
        except Exception, e:
            print 'A new file has been created!'
            directories = path.split("/")
            #In case the path string is '/example/example', instead of 'example/example'
            if directories[0] == '':
                directories.pop(0)
            #Retrieving the file to be loaded, it is the last one in the list
            fileName = directories.pop()
            newPath = ''
            #In case the file is to be created in the root folder there will be no iteration, therefore frk will be empty
            frk = ''
            for directory in directories:
                frk = '/'
                #Browsing through the directories and creating them if necessary
                newPath = newPath + directory
                if not os.path.exists(newPath):
                    os.makedirs(newPath)
                newPath = newPath + frk
            newPath = newPath + frk + fileName
            #Here it lies the problem... The method X (loadPath) will instance class A (Log) and call method E (error)
            Log().error(e)
            return open(newPath, 'w')


class Log(object):

    #Opens all log files and loads the current number of lines for each
    def __init__(self):

        errors_path = "logs/"+strftime("%Y-%m-%d", gmtime())+"/errors_log.txt"
        #Now that the class is being instanced it calls method X (loadPath) again
        self.errors_log = PyUtility().loadPath(errors_path)
        self.errors_log.seek(0,2)

    def error(self, e):
        self.errors_log.write("Error ["+str(self.errors_count)+"] @ "+strftime("%Y:%m:%d:%H:%M:%S", gmtime())+": "+str(e)+"\n")
        self.errors_count = self.errors_count + 1

我的部分解决方案并不令我满意,我在 Log class 中创建了另一个 "loadPath" 方法,我只是将其命名为 "loadLog" 并且它工作正常。但是我想知道是否还有其他选择。

干杯[]'

是的,有一个简单的解决方案。

就我个人而言,我喜欢让方法尽量简短。我并不是说您必须遵循我的个人喜好才能发挥作用,但在我看来,有一种非常简单的方法可以解决此类问题。每当一个函数开始变得像 def loadPath() 这样大(我知道有些人会说它很小)时,您很有可能可以很好地重构它。我对 big 的定义是实现细节与意图的比例过高。换句话说,我倾向于 declarative programming.

那现在呢?

简单。只是重构它。

import os

class PyUtility(object):

    def loadPath(self, path, op='r+'):
        print 'loadPath()'
        try:
            return open(path.lstrip('/'), op)
        except Exception, e:
            Log().error(e)
            return open(createvalidpath(path), 'w')

def createvalidpath(path):

    directories = path.split("/")
    #In case the path string is '/example/example', instead of 'example/example'
    if directories[0] == '':
        directories.pop(0)
    #Retrieving the file to be loaded, it is the last one in the list
    fileName = directories.pop()
    newPath = ''
    #In case the file is to be created in the root folder there will be no iteration, therefore frk will be empty
    frk = ''
    for directory in directories:
        frk = '/'
        #Browsing through the directories and creating them if necessary
        newPath = newPath + directory
        if not os.path.exists(newPath):
            os.makedirs(newPath)
        newPath = newPath + frk

    return newPath + frk + fileName

class Log(object):

    #Opens all log files and loads the current number of lines for each
    def __init__(self):

        errors_path = "logs/"+strftime("%Y-%m-%d", gmtime())+"/errors_log.txt"

        self.errors_log = (
            open(errors_path, 'w') if os.path.isfile(errors_path) 
            else open(createvalidpath(errors_path), 'w')
        )
        self.errors_log.seek(0,2)

    def error(self, e):
        self.errors_log.write("Error ["+str(self.errors_count)+"] @ "+strftime("%Y:%m:%d:%H:%M:%S", gmtime())+": "+str(e)+"\n")
        self.errors_count = self.errors_count + 1

你看,createvalidpath 现在只是一个模块级函数(为什么不呢?)。没有什么说函数必须都是 class 的一部分。毕竟,似乎它可能会从许多不同的地方被调用。如果最终你得到了一组执行文件路径操作的相关函数,并且如果它们应该共享状态是有意义的,那么创建一个新的 class 并从那里开始。

避免循环调用

如您所见,Log 可以安全地调用 createvalidpath 如果需要 。只有 loadPath 需要记录错误,而不是 createvalidpath。所以,本质上,这两个函数都执行一个具体的动作、意图等。当你写一个长函数时这样想:Is there a good chance that buried in this function I may have to re - 单独使用它的一部分? 如果是,重构它。

顺便说一下,这个位是不必要的...

if path[0] == '/':
    path = path.lstrip('/')

我改成了:

return open(path.lstrip('/'), op)

因为最终如果前面没有 '/',它会 return 结果原样。好处是您可以进一步简化代码。