在Python中使用指针地址调用函数

3 投票
2 回答
4009 浏览
提问于 2025-04-17 09:07

我有一个简单的函数,想在两个不同的程序运行中调用它。第一次运行程序时,我把这个函数的指针保存到一个文件里:

import cPickle

def test():
    pass

def main():
    a = test
    pFile = open('test.txt', 'wb')
    cPickle.dump(a, pFile)
    pFile.close()

第二次我想加载这个文件,然后执行保存在对象里的函数:

import cPickle

def test():
    pass

def main():
    pFile = open('test.txt', 'rb')
    a = cPickle.load(pFile)
    pFile.close()
    a() 

需要注意的是,使用cPickle时,这个方法是有效的,这有点奇怪,因为我原以为这基本上是一个指向函数的指针,而这个指针在运行时会改变?当我打印'a'时,它给我的结果是:function test at 0x0351C170:。

所以我想问的第一个问题是,为什么这能工作,尽管引用地址在运行时应该会改变?

我的第二个问题是,如果它没有改变或者以某种方式不相关,我怎么能仅仅通过字符串:function test at 0x0351C170:来执行这个函数呢?比如说,像这样:

def test():
    print 'test'

a = test
a()          #outputs: 'test'

b = str(a)   #<function test at 0x03509170>
eval(b)()    #error

2 个回答

3

你不能在某个特定的地址执行一个函数。

没错,地址在运行时会发生变化。当cPickle加载文件时,它会创建一个新的函数,而你看到的就是这个新函数。这个新函数的地址和原来的函数是不同的。

2

可以查看pickle 的文档

以下类型是可以被“腌制”的:

  • None(空值)、True(真)、和 False(假)
  • 整数、长整数、浮点数、复数
  • 普通字符串和 Unicode 字符串
  • 只包含可“腌制”对象的元组、列表、集合和字典
  • 在模块顶层定义的函数
  • 在模块顶层定义的内置函数
  • 在模块顶层定义的类
  • 这些类的实例,其 __dict____setstate__() 是可“腌制”的(具体细节请参见“腌制协议”部分)

所以,pickle 模块实际上是把 Python 的字节码写入到腌制文件中。当这个腌制文件被重新加载时,函数会从代码对象中重新创建。

至于你问题的第二部分,不,单单知道内部地址值是无法直接调用 Python 代码的。

撰写回答