不使用“全局”访问函数外部的函数变量[重复]

2025-02-13 08:35:00
admin
原创
38
摘要:问题描述:我正在尝试访问 Python 中函数外部的局部函数变量。我可以使用全局变量来使这样的代码工作:bye = '' def hi(): global bye bye = 5 sigh = 10 hi() print(bye) 接下来,我尝试了此代码,希望无需使用即可访问bye外...

问题描述:

我正在尝试访问 Python 中函数外部的局部函数变量。

我可以使用全局变量来使这样的代码工作:

bye = ''
def hi():
    global bye
    bye = 5
    sigh = 10

hi()
print(bye)

接下来,我尝试了此代码,希望无需使用即可访问bye外部:hi()`global bye`

def hi():
    bye = 5 
    sigh = 10
    return

hi()
x = hi()
print(x.bye)

这给出了AttributeError: 'NoneType' object has no attribute 'bye'

接下来我尝试:

def hi():
    bye = 5
    sigh = 10
    return bye

hi()
x = hi()
print(x.bye)

这并没有改善事情;我明白AttributeError: 'int' object has no attribute 'bye'

有没有一种方法可以在不使用全局变量的情况下访问函数bye外部的局部函数变量(hi()),并且不打印出该sigh变量?我该怎么做?


解决方案 1:

您可以按照以下步骤进行操作(当我测试它/它们时,它在 Python v2.7.17 和 v3.8.1 中都有效):

def hi():
    # other code...
    hi.bye = 42  # Create function attribute.
    sigh = 10

hi()
print(hi.bye)  # -> 42

函数是 Python 中的对象,可以赋予任意属性。

如果您经常要做这种事情,那么可以通过创建一个函数装饰器来实现更通用的功能,该函数装饰器会this在每次调用被装饰的函数时添加一个参数。

这个附加参数将为函数提供一种引用自身的方法,而无需将其名称明确嵌入(硬编码)到定义的其余部分中,并且类似于类方法自动接收作为其第一个参数的实例参数,该参数通常被命名self- 我选择了不同的东西以避免混淆,但就像self参数一样,它可以被命名为任何你想要的。

以下是该方法的一个例子:

def add_this_arg(func):
    def wrapped(*args, **kwargs):
        return func(wrapped, *args, **kwargs)
    return wrapped

@add_this_arg
def hi(this, that):
    # other code...
    this.bye = 2 * that  # Create function attribute.
    sigh = 10

hi(21)
print(hi.bye)  # -> 42

笔记

这不适用于类方法。只需使用self已传递给方法的实例参数(按惯例命名),而不是方法的名称。您可以通过 引用类级属性type(self)。请参阅类中的函数属性。

解决方案 2:

问题是您print(x.bye)在设置x为字符串后调用的。运行时,x = hi()它会运行 hi() 并将 x 的值设置为 5(bye 的值;它不会将 x 的值设置为对 bye 变量本身的引用)。例如:bye = 5; x = bye; bye = 4; print(x)打印 5,而不是 4。

此外,您不必运行hi()两次,只需运行x = hi(),而不是hi(); x=hi()(您的方式是运行 hi(),不对结果值 5 执行任何操作,然后重新运行相同的 hi() 并将 5 的值保存到 x 变量。

所以完整的代码应该是

def hi():
    bye = 5
    sigh = 10
    return bye 
x = hi()
print(x)

如果要返回多个变量,一种选择是使用列表或字典,具体取决于您的需要。例如:

def hi():
    return { 'bye': 5, 'sigh': 10 }
x = hi()
print x['bye']

解决方案 3:

 def hi():
     bye = 5
     return bye  

print hi()

解决方案 4:

为了能够访问局部函数的变量,可以添加函数名称并在局部变量名称前添加一个点(然后,当然,使用此构造在函数主体内和函数外部调用变量)。此解决方案适用于 Python 3.7.4。

例如:

def func(): # define a function
    # here y is a local variable, which I want to access; func.y 
    # defines a method for my example function which will allow me to  
    # access function's local variable y
    func.y = 4 
    x = func.y + 8
    return x

func() # now I'm calling the function
a = func.y # I put its local variable into my new variable
print(a) # and print my new variable

解决方案 5:

你可以做类似的事情:

def static_example():
   if not hasattr(static_example, "static_var"):
       static_example.static_var = 0
   static_example.static_var += 1
   return static_example.static_var

print static_example()
print static_example()
print static_example()

解决方案 6:

如果要避免global,一种可行的方法是定义一个类。每个类实例都有自己的属性;还有一个类属性空间,实例可以在其中共享一个属性。

如果您是 Python 新手,面向对象编程可能很难入门,但现在可能是开始尝试它的好时机。

class Thing:
    shared = "foo"

    def __init__(self):
        """
        This gets called when you create a new Thing()
        """
        self.bar = "baz"  # default value for new instances

    def get_bar(self):
        return self.bar

    def set_bar(self, value):
        self.bar = value

现在,让我们创建两个实例。

first = Thing()
second = Thing()

get_bar在类似本例的简单示例中,和方法set_bar并非必需。您还可以执行

second.bar = "ick"
print(second.bar)
# "ick"
print(first.bar)
# "baz"

(尽管对于更复杂的情况,您可能希望要求用户调用 setter 和 getter 方法;有办法强制执行此操作 - 例如参见使用 getter 和 setter 的 Pythonic 方式是什么?)

如果通过一个实例更改类属性,则在其他实例中它也不会被更改。

second.shared = "poo"
print(first.shared)
# "foo"

但是如果你在类本身中改变它,它将在所有未单独覆盖共享值的实例中被改变。

Thing.shared = "zoom"
print(first.shared)
# "zoom"
print(second.shared)
# "poo", still

回顾一下,你Thing通过调用 来创建一个新实例Thing();这将__init__在返回新实例之前运行该方法。在类内部,实例是每个(非静态、非类)方法的第一个参数,并且通常被调用(尽管就 Python 解释器而言,如果你愿意,self你可以调用它)。shirley

类还有很多内容;主要的卖点可能是您可以创建从其父类继承但可以覆盖某些行为的子类(常见的例子通常涉及现实世界的概念,如动物或车辆,但类可以是任何您想要创建类型并封装其行为的东西,并且可能覆盖派生类型中的一些方法)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用