Python中类方法的长参数列表:local,argument或class atribute?

时间:2018-01-17 14:24:04

标签: python design-patterns

我有一个包含许多函数的Python类。评估每个函数需要一长串常量(几十个);每个函数的常量都不同。每个函数将被调用多次(数百万),因此性能是一个主要问题。在可读性和速度方面,处理这种情况的正确方法是什么? (我对python来说比较新)

我可以创建常量类属性,但这似乎与范围提供的安全性相冲突(每个常量仅在单个函数中本地使用)。此外,能够在不同的功能中使用相同的变量名称将是方便的。此外,我发现所有self.都会使代码无法读取,尤其是在尝试将行长度保持在79以下时。

我现在在每个函数的开头都有本地定义的常量。这是相当清楚的,但我不确定它在性能方面是否最佳?是否为每个函数调用分配和释放了新内存?特别是因为你显然无法在Python中声明适当的常量。

将每个函数的参数放在一个单独的类中并将该类的对象作为参数传递可能会更好吗?这将保持适当的范围,同时确保每个常量只定义一次?

1 个答案:

答案 0 :(得分:1)

我使用单一参数r的逻辑映射作为示例运行了一些速度测试。在函数开头本地定义r可以获得最佳性能,同时将r设置为类属性或将其作为参数传递给函数(单独或作为参数实例的属性) class)将计算时间提高了大约10%。所以我认为解释器认识到在创建对象时本地定义的r是常量。 (请注意,我只使用一个参数进行测试,因此在更复杂的模型中差异可能会更大。)

如果有人好奇,以下是测试代码:

import matplotlib.pyplot as plt
import timeit

# Define class
class Mod:

    def __init__(self):
        self.reset()
        # self.r = 3.9 # -> uncomment when testing class attribute
        return

    def reset(self):
        self.x = 0.5

    def step(self): # -> add r when testing argument

        # ARGUMENT
        # self.x = r*self.x*(1-self.x) # +10% computation time

        # CLASS ATTRIBUTE
        # self.x = self.r*self.x*(1-self.x)  # +10% computation time

        # LOCAL
        r = 3.9
        self.x = r*self.x*(1-self.x)

# Length of test
trials = int(1e5)
T = int(1e3)

# r = 3.9 # -> uncomment when testing class attribute

# start timer
t0 = timeit.default_timer()

for _ in range(trials):
    x = []
    m.reset()
    for _ in range(T):
        m.step()  # -> add r when testing argument
        x.append(m.x) # do something with data to avoid interpreter tricks

# print computation time
print(timeit.default_timer() - t0)

plt.plot(x) 
plt.show()