我是靠谱客的博主 靓丽冰淇淋,最近开发中收集的这篇文章主要介绍python动态属性_Python动态函数属性,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在尝试实现动态排序时,我遇到了一个有趣的问题.

给出以下代码:

>>> l = []

>>> for i in range(2):

>>> def f():

>>> return f.v

>>> f.v = i

>>> l.append(f)

你必须要小心如何使用l中的函数:

>>> l[0]()

1

>>> l[1]()

1

>>> [h() for h in l]

[1, 1]

>>> [f() for f in l]

[0, 1]

>>> f = l[0]

>>> f()

0

>>> k = l[1]

>>> k()

0

>>> f = l[1]

>>> k()

1

>>> del f

>>> k()

NameError: global name 'f' is not defined

函数的行为取决于当前的f.

我该怎么做才能避免这个问题?如何设置不依赖于函数名称的函数属性?

更新

阅读你的评论和答案,这是我的实际问题.

我有一些数据,我想根据用户输入排序(所以我不知道提前排序标准).用户可以选择应用连续排序的数据部分,这些排序可以是升序或降序.

所以我的第一次尝试是循环用户输入,为每个标准定义一个函数,将此函数存储在列表中,然后将此列表用于排序的键,如下所示:key = lambda x:[f(x)for f in functions ].为了避免将条件乘以函数本身,我在函数定义之前计算了一些所需的值,并将它们绑定到函数(具有不同预先计算值的不同函数).

在调试时,我理解函数属性不是这里的解决方案,所以我确实用__call__方法编写了一个类.

解决方法:

问题是由于返回f.v加载全局f,而不是你想要的那个.你可以通过反汇编代码看到这个:

>>> dis.dis(l[0])

3 0 LOAD_GLOBAL 0 (f)

3 LOAD_ATTR 1 (v)

6 RETURN_VALUE

在填充l的循环之后,f是对最后创建的闭包的引用,如下所示:

>>> l

[, ]

>>> f

因此,当你调用l [0]()时,它仍会加载指向最后创建的函数的f,并返回1.当你通过执行f = l [0]重新定义f时,全局f现在指向第一个功能.

你似乎想要的是一个具有状态的函数,它实际上是一个类.你可以这样做:

class MyFunction:

def __init__(self, v):

self.v = v

def __call__(self):

return self.v

l = [MyFunction(i) for i in range(2)]

l[0]() # 0

l[1]() # 1

虽然首先解释您的实际问题可能是个好主意,因为可能有更好的解决方案.

1:为什么不加载全局f而不是当前实例,你可能会问?

回想一下,当你创建一个类时,你需要传递一个self参数,如下所示:

# ...

def my_method(self):

return self.value

self实际上是对象的当前实例的引用.这就是Python知道加载属性值的位置.它知道它必须查看self引用的实例.所以当你这样做时:

a.value = 1

a.my_method()

self现在是对a的引用.

所以当你这样做时:

def f():

return f.v

Python无法知道实际上是什么.它不是参数,因此必须从其他地方加载它.在您的情况下,它是从全局变量加载的.

因此,当你执行f.v = i时,当你为f的实例设置属性v时,无法知道你在函数体中引用了哪个实例.

标签:python

最后

以上就是靓丽冰淇淋为你收集整理的python动态属性_Python动态函数属性的全部内容,希望文章能够帮你解决python动态属性_Python动态函数属性所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部