在函数中使用“静态”变量以便稍后返回值的方法是否存在?

huangapple go评论93阅读模式
英文:

Is there a way to use "static" variables in a function to return values later on?

问题

我有以下输入:

[['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '10', '10', '10', '10', '10', '0', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0', '0', '10', '10', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0', '0', '10', '10', '0', '0'],
['0', '0', '10', '10', '10', '10', '10', '10', '0', '0', '0', '0', '10', '10', '10', '10', '0', '0', '0'],
['0', '0', '0', '10', '10', '10', '10', '10', '0', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '10', '10', '0', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '10', '10', '0', '0', '0', '10', '10', '10', '10', '10', '10', '0', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']]

对于以下函数:

def assign_points(lists):
    """
    Assigns points from a list of lists to Vec4 objects.
    ...
    """
    z_max = float('-inf')
    z_min = float('inf')
    
    points = []
    for y, l in enumerate(lists):
        for x, point in enumerate(l):
            try:
                z, color = parse_point(point)
                if color is None:
                    color = no_color(z)
                points.append(Vec4(x, y, z, 0, color))
                
                # Update z_max and z_min if necessary
                if z > z_max:
                    z_max = z
                if z < z_min:
                    z_min = z

            except MyWarning as e:
                exit(f"Error on line {str(y)}, item {str(x)}: {e}")
    
    return points, z_max, z_min

然而,我的问题是:

  1. 我觉得assign_points函数太臃肿了,做了太多的事情并返回了太多的结果。
  2. 输入的列表可能会很大,我认为多次循环遍历它们是浪费的。
  3. 我不确定全局变量是否是最佳实践。

我考虑过编写一个函数来存储这些值,并且(根据作为参数的标志)在assign_points之外调用时返回最大值。但我很确定Python没有静态变量(对吗?)

你会如何解决这个问题?我应该保持现状,还是使用全局变量,或者采取第三种选择?

英文:

I have the following input:

[[&#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;10&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;],
[&#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;, &#39;0&#39;]]

For the following function:

def assign_points(lists):
&quot;&quot;&quot;
Assigns points from a list of lists to Vec4 objects.
...
&quot;&quot;&quot;
z_max = float(&#39;-inf&#39;)
z_min = float(&#39;inf&#39;)
points = []
for y, l in enumerate(lists):
for x, point in enumerate(l):
try:
z, color = parse_point(point)
if color is None:
color = no_color(z)
points.append(Vec4(x, y, z, 0, color))
# Update z_max and z_min if necessary
if z &gt; z_max:
z_max = z
if z &lt; z_min:
z_min = z
except MyWarning as e:
exit(f&quot;Error on line {str(y)}, item {str(x)}: {e}&quot;)
return points, z_max, z_min

However

My problem is that:

  1. I feel assign_points is too bloated and does/returns too much.
  2. the input lists can get quite big and I think looping trough them more than once is wasteful
  3. I'm not sure global vars is best practice

I thought about doing a function that stored the values and (depending on a flag as argument) returned the maximum values once called outside assign_points. But I'm pretty sure python doesn't have static vars (right?)

How would you go about this problem? Should I leave it as is or make global vars or do a 3rd option?

答案1

得分: 1

如评论中建议的那样,定义自己的类将允许您实例化和操作对象以满足您的需求。

由于似乎有三个相关的值(pointsz_maxz_min),您可以让您的类继承自namedtuple。然后,assign_points可以作为您的类的方法创建:

from collections import namedtuple

class Vec4Obj(namedtuple('Vec4Obj', ['points', 'z_max', 'z_min'])):
    def __new__(cls):
        return super().__new__(cls, [], float('-inf'), float('inf'))

    def assign_points(self, lists: list):
        for y, l in enumerate(lists):
            for x, point in enumerate(l):
                try:
                    z, color = parse_point(point)
                    if color is None:
                        color = no_color(z)
                    self.points.append(Vec4(x, y, z, 0, color))
                    
                    # 如果需要,更新 z_max 和 z_min
                    if z > self.z_max:
                        self.z_max = z
                    if z < self.z_min:
                        self.z_min = z

                except Warning as e:
                    exit(f"第 {str(y)} 行,第 {str(x)} 项出错:{e}")

您可以定义其他方法。例如,可以编写一个只接受一个列表和一个 y 值的方法,以避免循环遍历所有列表,从而一次添加较少的点。

使用您的类将如下所示:

my_obj = Vec4Obj() # 实例化,初始值为 Vec4Obj(points=[], z_max=-inf, z_min=inf)

my_obj.assign_points(lists) # 将点添加到 my_obj.points,并设置 my_obj.z_min 和 my_obj.z_max
英文:

As suggested in the comments, defining your own class would allow you to instantiate and manipulate objects to your liking.

Since there seem to be three relevant values (points, z_max and z_min) you could let your class inherit from namedtuple. assign_points can then be created as a method of your class:

from collections import namedtuple

class Vec4Obj(namedtuple(&#39;Vec4Obj&#39;, [&#39;points&#39;, &#39;z_max&#39;, &#39;z_min&#39;])):
    def __new__(cls):
        return super().__new__(cls, [], float(&#39;-inf&#39;), float(&#39;inf&#39;))

    def assign_points(self, lists: list):
        for y, l in enumerate(lists):
            for x, point in enumerate(l):
                try:
                    z, color = parse_point(point)
                    if color is None:
                        color = no_color(z)
                    self.points.append(Vec4(x, y, z, 0, color))
                    
                    # Update z_max and z_min if necessary
                    if z &gt; self.z_max:
                        self.z_max = z
                    if z &lt; self.z_min:
                        self.z_min = z

                except Warning as e:
                    exit(f&quot;Error on line {str(y)}, item {str(x)}: {e}&quot;)

You can define other methods. For instance one that would take only one list and a y value to avoid looping over all lists, hence adding fewer points at once.

Using your class would look like:

my_obj = Vec4Obj() # instantiate with value Vec4Obj(points=[], z_max=-inf, z_min=inf)

my_obj.assign_points(lists) # add points to my_obj.points and set my_obj.z_min and my_obj.z_max

huangapple
  • 本文由 发表于 2023年7月27日 17:33:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778374.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定