当前位置:首页 > 技术 > 正文内容

Python 的 getattr/setattr 与 pybind11 中的 attr 相关函数

访客 技术 2026年10月15日 1

Python 内建函数

getattr

getattr 是 Python 的内建函数。它用于获取对象指定名称的属性值。

函数签名:

getattr(object, name)
getattr(object, name, default)
  • object: 需要从中获取属性的对象。
  • name: 属性的名称,必须是字符串。
  • default: (可选) 如果属性不存在时返回的默认值。

如果 name 指定的属性存在,则返回该属性的值。例如,getattr(x, 'foobar') 等价于 x.foobar。

如果属性不存在:

  • 如果提供了 default 参数,则返回 default。
  • 否则,会抛出 AttributeError。

注意:属性名 name 不一定需要是合法的 Python 标识符。但是,私有属性(名称前有两个下划线)需要手动进行名称 mangling 才能通过 getattr 访问。

setattr

setattr 是 Python 的内建函数,与 getattr 相对应。它用于设置对象的属性值。

函数签名:

setattr(object, name, value)
  • object: 需要设置属性的对象。
  • name: 属性的名称,必须是字符串。
  • value: 要赋给属性的值。

name 可以是现有属性的名称,也可以是新属性的名称。只要对象允许,函数就会将 value 赋给该属性。例如,setattr(x, 'foobar', 123) 等价于 x.foobar = 123。

属性名 name 同样不一定需要是 Python 标识符。如果属性名不是标识符,则无法使用点运算符(.)访问,但仍可通过 getattr 等函数访问。

注意:与 getattr 类似,设置私有属性也需要手动进行名称 mangling。

测试示例

创建一个名为 test.py 的文件:

class Animal:
    legs = 4

    def run(self):
        print("I'm running!")

if __name__ == "__main__":
    a = Animal()

    print("Initial leg value:", getattr(a, "legs"))

    setattr(a, "legs", 2)
    print("After set to 2:", getattr(a, "legs"))

    print("run method:", getattr(a, "run"))
    print("Call run method:")
    getattr(a, "run")()

运行结果:

Initial leg value: 4
After set to 2: 2
run method: <bound method Animal.run of <__main__.Animal object at 0x...>>
Call run method:
I'm running!

pybind11 - Python 内建函数映射

pybind11 提供了 C++ 函数来映射 Python 的内建函数,这些函数通常与 Python 的版本行为一致。

py::getattr

pybind11 提供了 py::getattr 函数来获取 C++ 中的 Python 对象属性。

函数签名示例:

object getattr(handle obj, handle name);
object getattr(handle obj, const char *name);
object getattr(handle obj, handle name, handle default_);
object getattr(handle obj, const char *name, handle default_);

py::setattr

pybind11 提供了 py::setattr 函数来设置 C++ 中的 Python 对象属性。

函数签名示例:

void setattr(handle obj, handle name, handle value);
void setattr(handle obj, const char *name, handle value);

测试示例 (pybind11 - getattr/setattr)

创建一个名为 demo.cpp 的文件:

#include <pybind11/pybind11.h>
#include <pybind11/embed.h> // py::scoped_interpreter
#include <string>

namespace py = pybind11;

int main() {
    // 启动 Python 解释器
    py::scoped_interpreter guard{};

    // 使用 py::exec 定义 class
    py::dict scope;
    py::exec(R"(
class Person:
    def __init__(self):
        self.name = "Alice"
    def greet(self):
        return "Hi, " + self.name

p = Person()
)", scope);

    // 从 scope 获取 Python 对象
    py::object obj = scope["p"];

    // 使用 py::getattr / py::setattr
    py::print("Via py::getattr:", py::getattr(obj, "name"));
    py::setattr(obj, "name", py::str("Charlie"));
    py::print("After py::setattr:", py::getattr(obj, "name"));
    py::print("Greeting:", py::getattr(obj, "greet")());

    return 0;
}

编译和运行(需要根据你的 Python 版本调整链接标志):

c++ -O3 -Wall -std=c++11 demo.cpp -o demo \
    $(python3 -m pybind11 --includes) \
    -lpython3.8 -pthread -ldl -lutil -lm
./demo

运行结果:

Via py::getattr: Alice
After py::setattr: Charlie
Greeting: Hi, Charlie

pybind11 - py::object_api::attr

pybind11 的 py::object 类提供了一个 attr 成员函数,用于更方便地访问和修改对象的属性。

obj.attr("attribute_name") 返回一个可以进行 get/set 操作的对象访问器。

测试示例 (pybind11 - attr)

修改 demo.cpp 文件:

#include <pybind11/pybind11.h>
#include <pybind11/embed.h>  // py::scoped_interpreter
#include <string>
#include <typeinfo> // For typeid

namespace py = pybind11;

int main() {
    // 启动 Python 解释器
    py::scoped_interpreter guard{};

    // 用 py::exec 定义 class
    py::dict scope;
    py::exec(R"(
class Person:
    def __init__(self):
        self.name = "Alice"
    def greet(self):
        return "Hi, " + self.name

p = Person()
)", scope);

    // 从 scope 取得 Python 对象
    py::object obj = scope["p"];

    // 取得属性
    py::print("Via .attr get:", obj.attr("name"));

    // 修改属性
    obj.attr("name") = "Bob";
    py::print("After .attr() set:", obj.attr("name"));

    // 呼叫方法
    py::print("Greeting:", obj.attr("greet")());

    // 检视型别
    // 注意:typeid().name() 返回的是 C++ 内部表示,可能不是直接的 Python 类型名
    py::print("Type of greet result:", typeid(obj.attr("greet")()).name());

    return 0;
}

使用相同的指令编译执行后结果如下:

Via .attr get: Alice
After .attr() set: Bob
Greeting: Hi, Bob
Type of greet result: N8pybind116objectE 

输出 N8pybind116objectE 是 pybind11::object 的 C++ 内部表示。

常用 pybind11 函数说明

py::scoped_interpreter

这是一个 RAII(Resource Acquisition Is Initialization)类,用于管理 Python 解释器的生命周期。它会在构造时初始化 Python 解释器,并在析构时关闭解释器并释放资源。在 scoped_interpreter 对象超出作用域后,不能再调用任何 Python API。

py::dict

这是 pybind11 对 Python 字典(dict)的封装。可以用来表示 Python 的字典对象,并进行读写操作。

py::exec

该函数允许从 C++ 字符串中执行 Python 代码。它支持执行 Python 语句(statements)。使用 C++11 的原始字符串字面量(raw string literals)可以方便地处理包含特殊字符的 Python 代码。

py::print

为了解决 C++ 的 std::cout 和 Python 的 print 在输出顺序上可能出现的问题,pybind11 提供了 py::print() 函数。该函数会将输出写入 Python 的 sys.stdout,确保输出的一致性。它模仿了 Python 的 print 函数,并支持 sep, end, file, flush 等可选参数。

py::str

这是 pybind11 对 Python 字符串(str)的封装。它允许将 C++ 字符串转换为 Python 字符串对象,或获取 Python 对象的字符串表示形式,类似于 Python 的 str() 函数。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。