【问题标题】:How to add new attributes to struct_spwd type while preserving its original attributes?如何在保留其原始属性的同时向 struct_spwd 类型添加新属性?
【发布时间】:2026-02-09 19:20:09
【问题描述】:

Python 有 spwd 模块来与影子密码文件交互。

您必须是 root 才能使用 spwd 模块。

>>> import spwd;

>>> a = spwd.getspnam('bin')

>>> type(a)
<class 'spwd.struct_spwd'>

>>> a.__gt__
<method-wrapper '__gt__' of spwd.struct_spwd object at 0x7fd017641b80>

现在我想为对象“a”(或类“struct_spwd”)添加一个新属性。我该怎么做?

继承不起作用。

import spwd

class Abc(spwd.struct_spwd):
    pass

我收到“TypeError: type 'spwd.struct_spwd' is not an accepted base type”。

向对象添加动态属性不起作用。

import spwd

a = spwd.getspnam('bin')
a.new_attribute = lambda: print('hello world')

我收到“AttributeError: 'spwd.struct_spwd' 对象没有属性 'new_attribute'”。

不过,使用委托可能会奏效。但我想保留它原有的属性。

import spwd

class Abc(object):
    def __init__(self, struct_spwd):
        self.struct_spwd = struct_spwd

    def __getattribute__(self, name):
        if name=='new_attribute':
            print('hello world')
        else:
            self.struct_spwd.__getattribute__(name)

a = spwd.getspnam('bin')
b = Abc(a)
b.new_attribute
b.__gt__

我得到“RuntimeError:比较中超出了最大递归深度”。

有什么想法吗?还是我应该使用其他方式来实现我的目标?谢谢。

【问题讨论】:

    标签: python


    【解决方案1】:
    class Wrapper(object):
        def __init__(self, wrapped):
            self.wrapped = wrapped
    
        def __getattr__(self, name):
            if name.startswith('sp_'):
                value = getattr(self.wrapped, name)
                setattr(self, name, value)
                return value
    
            raise AttributeError
    

    代码还缓存这些值,因此每个成员只调用一次__getattr__

    【讨论】:

    • 感谢您的回答。我不喜欢明确的过滤和引发异常。我更喜欢将它们都发送到包装对象。
    • 我添加了过滤,因为阴影对象还包含其他属性,即n_unnamed_fields 等等......但如果需要,欢迎您删除:D
    【解决方案2】:

    看看这个帖子:

    How is the __getattribute__ method used?

    你要使用的是getattr():

    class Abc(object): def __init__(self, struct_spwd): self.struct_spwd = struct_spwd def __getattr__(self, name): if name=='new_attribute': print('hello world') else: return getattr(self.struct_spwd, name)

    【讨论】: