首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift的@dynamicMemberLookup有没有Python等价物?

Swift的@dynamicMemberLookup有没有Python等价物?
EN

Stack Overflow用户
提问于 2019-11-15 03:59:18
回答 2查看 242关注 0票数 1

Swift中,您可以定义@dynamicMemberLookup (see documentation)来直接访问嵌套在另一个类型中的属性。有没有Python的等价物?

我想用Python实现的示例

假设我有一个包含成员的类,例如:

代码语言:javascript
复制
c = OuterClass()
c.inner_class = ClassWithManyMembers()
c.inner_class.member1 = "1"
c.inner_class.member2 = "2"
c.inner_class.member3 = "3"

我希望能够获取/设置这些成员,而不必每次都键入inner_class

代码语言:javascript
复制
print(c.member1)  # prints "1"
c.member1 = 3
print(c.member1)  # prints "3"

Swift (Source)中的示例:

按成员名称进行动态成员查找

代码语言:javascript
复制
@dynamicMemberLookup
struct DynamicStruct {
    let dictionary = ["someDynamicMember": 325,
                      "someOtherMember": 787]
    subscript(dynamicMember member: String) -> Int {
        return dictionary[member] ?? 1054
    }
}
let s = DynamicStruct()

// Use dynamic member lookup.
let dynamic = s.someDynamicMember
print(dynamic)
// Prints "325"

按键路径动态查找成员

代码语言:javascript
复制
struct Point { var x, y: Int }

@dynamicMemberLookup
struct PassthroughWrapper<Value> {
    var value: Value
    subscript<T>(dynamicMember member: KeyPath<Value, T>) -> T {
        get { return value[keyPath: member] }
    }
}

let point = Point(x: 381, y: 431)
let wrapper = PassthroughWrapper(value: point)
print(wrapper.x)

我在Python中唯一的想法是将所有嵌套属性直接monkey-patch到外部类。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-15 07:40:06

通常,当您想要重复访问内部对象时,可以只保存对它的引用。

代码语言:javascript
复制
c = OuterClass()
c.inner_class = ClassWithManyMembers()

ic = c.inner_class
print(ic.member1)
print(ic.member2)
print(ic.member3)

ic.member1 = "5"
票数 1
EN

Stack Overflow用户

发布于 2019-11-15 05:03:49

我建议不要将类嵌套在另一个类中,但如果您必须这样做,请尝试这样做:

代码语言:javascript
复制
class MetaOuter(type):
    def __getattr__(cls, attr):
        for member in cls.__dict__.values():
            if hasattr(member, attr):
                return getattr(member, attr)
        raise AttributeError(attr)

    def __setattr__(cls, attr, value):
        for member in cls.__dict__.values():
            if hasattr(member, attr):
                setattr(member, attr, value)
                return
        super().__setattr__(attr, value)


class Outer(metaclass=MetaOuter):
    a = 0

    class Inner:
        x = 1
        y = 2

现在,Outer中嵌套类的任何属性都可以作为Outer的属性使用(并且可以写入

代码语言:javascript
复制
>>> Outer.x, Outer.y
(1, 2)
>>> Outer.a # Accessing regular attributes still works as usual
0
>>> Outer.x = True
>>> Outer.Inner.x
True

如果您需要嵌套多个级别,请对任何内部封装类使用相同的元类:

代码语言:javascript
复制
class Outer(metaclass=MetaOuter):
    a = 0

    class Inner(metaclass=MetaOuter):
        x = 1
        y = 2

        class Innerer:
            z = 42
代码语言:javascript
复制
>>> Outer.a, Outer.x, Outer.y, Outer.z
(0, 1, 2, 42)
>>> Outer.z = -1
>>> Outer.z
-1

注意:请注意,如果您试图访问在多个嵌套类中找到的属性,则无法确定该属性将来自哪个类。在这种情况下,一种更可预测的实现将是处理将被查找的某种关键路径,但这本质上与Python默认提供的(例如,Outer.Inner.Innerer.z)相同。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58864852

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档