Python:静态变量装饰器

2023-12-11

我想创建一个如下所示的装饰器,但我似乎想不出可行的实现。我开始认为这是不可能的,但我想我应该先问你们。

我意识到在 Python 中还有各种其他方法来创建静态变量,但我发现这些方法很丑陋。如果可能的话,我真的很想使用下面的语法。

@static(x=0)
def f():
    x += 1
    print x

f() #prints 1
f() #prints 2

我不在乎是否实施static是长还是黑客,只要它像上面那样工作即可。

我创建了这个版本,但它只允许<function>.<varname>语法,如果函数和变量名较长,它很快就会变得很麻烦。

def static(**assignments):
    def decorate(func):
        for var, val in assignments.items():
            setattr(func, var, val)
        return func
    return decorate

我想到但无法实施的各种事情是:

  1. 将 f (装饰函数)更改为可调用类,并以某种方式将静态变量存储在self透明地。
  2. 修改装饰器内 f() 的全局变量,并以某种方式将“global x”语句插入到 f 的代码中。
  3. 将 f 更改为生成器,我们手动绑定变量,然后直接执行 f 的代码。

当你的装饰器获得函数对象时f,它已经被编译了——具体来说,它是根据以下知识编译的:x是本地的(因为它被分配了+=分配),正常优化(在2.*您可以通过开始以惊人的性能代价来击败优化f with exec ''; in 2.*,你无法击败优化)。本质上,要使用您想要的语法,您必须重新编译f(通过恢复其源代码,如果您知道它们将在运行时可用,或者更困难的是,通过字节码黑客)使用某种方式修改的源代码 - 一旦您决定这样做,最简单的方法可能是更改x into f.x整个身体f.

就我个人而言,如果当我发现自己与语言(或其他技术)进行如此激烈的斗争,以至于我试图屈服于自己的意志来强加我的愿望时,我承认我要么使用了错误的语言(或其他技术) ,如果这些愿望绝对至关重要,那么解决方案必须是改变技术;或者,如果这些愿望不是那么重要,就放弃它们。

不管怎样,我放弃了试图扭曲语言,使其远离其明显的设计意图:即使我确实想出了一些古怪的、脆弱的拼凑,它无疑是无法维护的。在这种情况下,Python 的意图非常明确:在函数内重新绑定的裸名是该函数的局部变量,除非明确指定为全局变量——句号。因此,您尝试使裸名(在函数内重新绑定)意味着与“当地人”完全不同的东西正是这种斗争。

Edit:如果你愿意放弃坚持使用裸名对于你的“静态”,突然间你不再与 Python 作斗争,而是“顺应语言的本质”(尽管存在设计问题)global [and nonlocal],但是,这是一个单独的咆哮;-)。因此,例如:

class _StaticStuff(object):
  _static_stack = []
  def push(self, d):
    self._static_stack.append(d)
  def pop(self):
    self._static_stack.pop()
  def __getattr__(self, n):
    return self._static_stack[-1][n]
  def __setattr__(self, n, v):
    self._static_stack[-1][n] = v
import __builtin__
__builtin__.static = _StaticStuff()

def with_static(**variables):
  def dowrap(f):
    def wrapper(*a, **k):
      static.push(variables)
      try: return f(*a, **k)
      finally: static.pop()
    return wrapper
  return dowrap

@with_static(x=0)
def f():
    static.x += 1
    print static.x

f()
f()

这就像你想要的那样,打印 1 然后打印 2。(我正在使用__builtin__使其使用起来最简单with_static当然,可以装饰任何模块中的函数)。您可以有几种不同的实现,但任何一个的关键点good实现是“静态变量”将是合格的 names, notbarenames——明确表明它们不是局部变量,玩弄语言的纹理,等等。 (类似的内置容器,以及基于它们的限定名称,should在Python的设计中已经使用了,而不是global and nonlocal设计故障,以指示其他类型的变量不是本地变量,因此不应使用裸名...好吧,您可以自己实现一个globvar与上述相同的特殊容器static那些,甚至不需要装饰,尽管我不太确定这对于nonlocal情况[也许with一些装饰和最少量的黑魔法...;=)])。

Edit:注释指出,当您仅装饰返回闭包的函数(而不是装饰闭包本身)时,给定的代码不起作用。没错:当然,你必须装饰使用的特定函数static(根据函数的定义,只能有一个——static变量!),而不是实际上不使用的随机函数static而是恰好与以下词汇有某种词汇联系does。例如:

def f():
  @with_static(x=0)
  def g():
    static.x += 1
    print static.x
  return g

x = f()
x()
x()

这有效,同时将装饰器移动到f代替g不会(也不可能)。

如果实际的需求不是关于静态变量(仅在单个函数中可见和可用),而是关于可在某个特定的函数包中使用的某种混合事物,则需要非常精确地指定(并且毫无疑问,实现方式非常不同,具体取决于实际规格是什么are)——理想情况下,这需要在一个新的、单独的 SO 问题中发生,因为这个(具体是关于static相反),而这个具体问题的答案已经足够大了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python:静态变量装饰器 的相关文章

随机推荐

  • Prolog 中的错误未定义过程

    我写了一条规则 parent georgie jessy child jessy georgio 但是 当我想证明 parent georgie jessy 我收到错误 parent 2 Undefined procedure child
  • 将纯色背景颜色动画化为图像

    我有一组 div 我希望它们每个都有不同的背景颜色 而悬停时过渡到背景图像所选网址的 到目前为止 我已经成功找到了平滑颜色 gt 图像转换的代码 但这需要 HTML 中的实际 img 代码 并且我需要这些 div 因为我将在其中放入文本 有
  • 从 C# Windows 应用程序读取/写入三星 Android 手机/平板电脑

    我正在编写一个 Windows C winforms 应用程序 它将图像从 PC 复制到 Android 设备的图像文件夹 Windows 文件资源管理器给了我这个路径 Computer SCH I535 Phone Images 但我无法
  • Android Studio 无法解析fragmentActivity 和ViewPager 导入

    我遵循开发可滑动选项卡的教程 当我导入时 import android support v4 app FragmentActivity import android support v4 view ViewPager Android Stu
  • 示例:使用 AsyncTask 的 Android 双向网络套接字

    我发现的大多数 Android 网络套接字示例都是单向的 我需要一个双向数据流的解决方案 我最终了解到了 AsyncTask 此示例演示如何从套接字获取数据并将数据发送回套接字 由于接收数据的套接字具有阻塞性质 因此该阻塞需要在 UI 线程
  • 如何让 Jenkins 上的 groovy 屏蔽变量的输出,就像处理凭证一样?

    Jenkins 上的 groovy 是否有一种方法可以获取任意字符串变量 例如对另一个服务的 API 调用的结果 并让 Jenkins 在控制台输出中屏蔽它 就像它自动从凭证管理器读取的值一样 更新的解决方案 要隐藏变量的输出 您可以使用掩
  • 声明与全局、局部和静态同名的变量

    我有以下代码片段 我必须分析输出是什么 include
  • 使用 Sunspot 从 Solr 索引中排除文章草稿

    我有一个名为 Article 的索引模型 我不希望 solr 索引未发布的文章 class Article lt ActiveRecord Base searchable do text title text body end end 我怎
  • Deviseomniauthable 因“无法找到有效的路径映射”而破坏 Omniauth 身份验证

    在我的项目中 我有两种类型的用户 求职者和招聘经理 求职者没有模型 他们只能使用从第三方提供商收到的数据来申请工作 同时通过 Omniauth 进行身份验证 招聘经理的信息存储在设计用户模型中 招聘经理还必须能够使用其公司的 Google
  • mysql where语句日期问题

    希望有人能帮忙 我想做的是从数据库中提取任何给定月份的所有结果 是否可以仅使用 mysql 查询 无 php 我使用一个模板应用程序 我唯一的访问权限是通过 mysql where 语句 所以我需要从 2013 04 01 算出月份是什么
  • 求解具有变量约束的非线性方程组

    使用 fsolve 求解非线性方程组的一些假设示例 from scipy optimize import fsolve import math def equations p x y p return x y 2 4 math exp x
  • 不使用主键的映射中流畅的 NHibernate 连接表

    我正在尝试从 2 个不通过主键相关的表创建一个实体 Tables CREATE TABLE employees ssn nvarchar 9 NULL active bit NULL employee id int IDENTITY 1 1
  • Android:如何制作带有 2 行文本和 RadioButton(单选)的 AlertDialog?

    如何制作包含如下行的列表对话框 FIRST LINE OF TEXT o lt this is a RadioButton second line of text 我知道我应该使用自定义适配器 通过这些视图传递行布局 实际上 我已经这样做了
  • 更新文档时出现错误:由于值未定义,转换为字符串失败

    我有一个简单的文档 其中包含名称 必需 和描述 可选 在我的模型中 我使用有效 ID 更新文档 并传递值为未定义的描述 因为我想从文档中删除此属性 但是 我收到以下错误 消息 转换为字符串失败 路径 描述 处的值 未定义 名称 CastEr
  • Magento:如何在客户信息字段中显示客户的电话号码

    我试图让客户的电话号码显示在客户帐户信息部分下 我知道电话号码属于客户地址部分 但我正在尝试重新设计客户帐户信息的外观 我为客户 ID 添加了一个新的自定义字段 并且可以使用以下代码显示它 因为客户 ID 属于 customer entit
  • 在 cakephp 中验证输入文件

    在 cakephp 中 我试图检查文件输入字段是否附加了文件 如果没有则输出错误 我已经在其他领域做到了这一点 但似乎无法让它在该领域发挥作用 这是模型 array notempty uploadeduploaded file gt arr
  • 将输入的数据存储在数组中[重复]

    这个问题在这里已经有答案了 我是 C 初学者 如果我的问题很蹩脚 请不要介意 在我编写的这个程序中 当我第一次使用 for 循环时 我预计数组中仅存储 3 个值 但它存储 4 个值 并且在下一个 for 循环中按预期显示 3 个值 我的问题
  • 如何避免触发器内的 ORA-04091 错误

    我在表 A 上有一个更新后触发器 触发器 A 可以对表 B 进行更改 我在表 B 上还有一个更新后触发器 触发器 B 它不进行任何更改 但查询表 A 以对非规范化进行一些健全性检查 因此触发器 B 可以通过以下两种方式之一触发 如果我直接更
  • 带重定向的 Node.js 包罗万象的路由始终使用 Angular 呈现索引页面,无论 url 是什么

    本质上当我使用包罗万象的路线并使用res redirect 无论我输入的网址如何 它总是会呈现索引 主页 即 Angular 似乎没有 看到 完整的网址 但是如果我放置res render index 在包罗万象的路线中一切正常 我不想重复
  • Python:静态变量装饰器

    我想创建一个如下所示的装饰器 但我似乎想不出可行的实现 我开始认为这是不可能的 但我想我应该先问你们 我意识到在 Python 中还有各种其他方法来创建静态变量 但我发现这些方法很丑陋 如果可能的话 我真的很想使用下面的语法 static