我正在寻找一种优雅的方法,使用一些嵌套的dicts和列表(即javascript样式的对象语法)在dict上使用属性访问来获取数据.
例如:
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}
Run Code Online (Sandbox Code Playgroud)
应该可以通过这种方式访问:
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
Run Code Online (Sandbox Code Playgroud)
我认为,如果没有递归,这是不可能的,但是什么是获得dicts的对象样式的好方法?
我想覆盖对类中一个变量的访问,但是通常会返回所有其他变量.我如何实现这一目标__getattribute__?
我尝试了以下(这也应该说明我正在尝试做什么),但我得到一个递归错误:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
Run Code Online (Sandbox Code Playgroud) 使用python属性,我可以这样做
obj.y
Run Code Online (Sandbox Code Playgroud)
调用函数而不是仅返回值.
有没有办法用模块做到这一点?我有一个我想要的案例
module.y
Run Code Online (Sandbox Code Playgroud)
调用函数,而不是只返回存储在那里的值.
我知道我可以通过执行以下操作动态地向对象添加实例方法:
import types
def my_method(self):
# logic of method
# ...
# instance is some instance of some class
instance.my_method = types.MethodType(my_method, instance)
Run Code Online (Sandbox Code Playgroud)
后来我可以打电话instance.my_method(),自我将被正确绑定,一切正常.
现在,我的问题:如何做同样的事情来获得用@property装饰新方法的行为?
我猜是这样的:
instance.my_method = types.MethodType(my_method, instance)
instance.my_method = property(instance.my_method)
Run Code Online (Sandbox Code Playgroud)
但是,这样做会instance.my_method返回一个属性对象.
在调查Ruby时,我遇到了这个问题来创建一个类似Struct的类:
Person = Struct.new(:forname, :surname)
person1 = Person.new('John', 'Doe')
puts person1 #<struct Person forname="John", surname="Doe">
Run Code Online (Sandbox Code Playgroud)
这为我提出了一些Python问题.我在Python中编写了一个[非常]基本的克隆机制:
def Struct(*args):
class NewStruct:
def __init__(self):
for arg in args:
self.__dict__[arg] = None
return NewStruct
>>> Person = Struct('forename', 'surname')
>>> person1 = Person()
>>> person2 = Person()
>>> person1.forename, person1.surname = 'John','Doe'
>>> person2.forename, person2.surname = 'Foo','Bar'
>>> person1.forename
'John'
>>> person2.forename
'Foo'
Run Code Online (Sandbox Code Playgroud)
Python中是否已有类似的机制来处理这个问题?(我通常只使用字典).
我如何获得Struct()创建正确__init__()参数的函数.(在这种情况下,我想尽可能执行person1 = Person('John', 'Doe')命名参数:person1 = Person(surname='Doe', forename='John')
我想,感兴趣的是,即使有更好的Python机制来解决问题2也是如此.
我想创建一个一次性"struct"对象来保存各种状态标志.我的第一个方法就是这个(javascript风格)
>>> status = object()
>>> status.foo = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'foo'
Run Code Online (Sandbox Code Playgroud)
绝对不是我的预期,因为这有效:
>>> class Anon: pass
...
>>> b=Anon()
>>> b.foo = 4
Run Code Online (Sandbox Code Playgroud)
我想这是因为object()没有__dict__.我不想使用字典,假设我不想创建Anon对象,还有其他解决方案吗?
我想创建一个具有某些属性的对象。我想动态添加它们。与向现有对象实例添加方法类似,但使用属性而不是方法。下面是一个简单的例子。
我喜欢动态创建:
class A():
@property
def a(self):
return self._a
@a.setter
def a(self, x):
self._a = 10*x
@property
def b(self):
return self._b
@b.setter
def b(self, x):
self._b = 10*x
Run Code Online (Sandbox Code Playgroud)
要使用方法来做到这一点,我会这样做:
class B():
def __init__(self):
for i in range(70,80):
self.__dict__[chr(i)] = types.MethodType(lambda self,x: x*i, self)
Run Code Online (Sandbox Code Playgroud)
对于我尝试过的属性:
class B():
def __init__(self):
for i in range(70,80):
def tmp(self, x):
self._x = i*x
self.__dict__[chr(i)] = property(fget=lambda self: self._i, fset=tmp)
Run Code Online (Sandbox Code Playgroud)
我也找到了types.DynamicClassAttribute,但我不确定这是否有帮助。
这里提出了一个相关问题,关于向类添加属性(在 python 2 中): Dynamically add @property in python。我不知道如何将其扩展到类的实例。
使用python,可以通过以下两种方法之一设置实例的属性:
>>> class Foo(object):
pass
>>> a = Foo()
>>> a.x = 1
>>> a.x
1
>>> setattr(a, 'b', 2)
>>> a.b
2
Run Code Online (Sandbox Code Playgroud)
还可以通过属性装饰器分配属性.
>>> class Bar(object):
@property
def x(self):
return 0
>>> a = Bar()
>>> a.x
0
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何为实例分配属性?
我的直觉是尝试这样的事情......
>>> class Doo(object):
pass
>>> a = Doo()
>>> def k():
return 0
>>> a.m = property(k)
>>> a.m
<property object at 0x0380F540>
Run Code Online (Sandbox Code Playgroud)
...但是,我得到了这个奇怪的属性对象.类似的实验产生了类似的结果.我的猜测是,在某些方面,属性与类的关系比实例更密切,但我不清楚内部工作是否足以理解这里发生了什么.
我正在为通过Pythonnet访问的C#API编写Python包装器类。当我想用自己的方法扩展API时,我决定使用此处概述的组合方法包装它:
C#API大量使用了我想在我的Python代码中模仿的属性。下面的最小示例显示了我当前使用C#Surface类的示例的方法,该类具有两个属性width和height:
class MySurface:
def __init__(api_surface):
self.api_surface = api_surface
@property
def width(self):
return self.api_surface.width
@width.setter
def width(self, value):
self.api_surface.width = value
@property
def height(self):
return self.api_surface.height
@height.setter
def height(self, value):
self.api_surface.height = value
Run Code Online (Sandbox Code Playgroud)
总共我必须处理大约50个属性。对于几组属性,我想添加自己的错误检查,类型转换等。我正在寻找一种Python方式定义属性,例如通过工厂或使用描述符。谢谢你的帮助!
编辑:我希望能够在python shell(即曲面)中使用制表符补全。{hit标签}应该建议surface.width和surface.height。用Greg概述的getattr方法似乎不可能做到这一点。
我基本上有一个围绕词典列表的精心设计的包装器:
class Wrapper(object):
def __init__(self, data):
self.data = data
def get(self, attr):
return [d[attr] for d in self.data]
Run Code Online (Sandbox Code Playgroud)
所以,
Wrapper([{'x': 23}, {'x': 42}, {'x': 5}]).get('x')
Run Code Online (Sandbox Code Playgroud)
回报[23, 42, 5].现在我想分配速记属性,以便Wrapper.x返回相同的Wrapper.get('x').我不知道data先验中存在哪些键,所以我目前的方法是(改编自这个问题:
class Wrapper(object):
def __init__(self, data):
self.data = data
for key in data[0].keys():
setattr(self, key, property(lambda self: self.get(key)))
Run Code Online (Sandbox Code Playgroud)
因此,假设数据的所有元素都具有相同的密钥,并且它们在python中都是有效的标识符.但是,Wrapper(...).x返回,<property at 0x10a3d4838>我做错了什么?
我正在编写一些天文馆软件的 Python 插件。这个插件带有访问天文馆软件命名空间内的对象的功能,但它们很麻烦,而且不是面向对象的。因此,我试图创建一个类来重载属性访问以简化编码。我希望能够做这样的事情,
rocket = RemoteObject('rocket')
rocket.color = blue
Run Code Online (Sandbox Code Playgroud)
将天文馆软件命名空间中火箭对象的颜色设置为蓝色。
如何定义属性__init__非常接近。我遇到的一个困难是我需要在创建实例时确定我的属性的名称。另一个困难是由于我对描述符的一般理解不足:属性调用正在返回或覆盖我的属性对象本身,而不是调用其 getter 和 setter。
这是我到目前为止所拥有的:
class RemoteObject(object):
def __init__(self,remote_object_name):
self.normalattr = 'foo'
self.normalmethod = lambda: 'spam'
for attrname in get_remote_object_attrnames(remote_object_name):
def _get(self):
return fetch_remote_attr_value(remote_object_name,attrname)
def _set(self,value):
set_remote_attr_value(remote_object_name,attrname,value)
setattr(self,attrname,property(_get,_set))
if __name__ == '__main__':
get_remote_object_attrnames = lambda name: {'apple','banana','cherry'}
fetch_remote_attr_value = lambda o,a: 'Reading %s.%s' % (o,a)
set_remote_attr_value = lambda o,a,v: 'Writing %s.%s = %s' % (o,a,v)
scene = RemoteObject('scene')
for x in scene.__dict__.items(): print x
print '-----'
print scene.normalattr …Run Code Online (Sandbox Code Playgroud) 我有一个包含文件名和类名的字典如何导入这个类名,我该如何创建这个类?
例:
classNames = { 'MCTest':MCTestClass}
Run Code Online (Sandbox Code Playgroud)
我想导入MCTest并创建MCTestClass.
python ×12
properties ×5
dynamic ×2
attributes ×1
class ×1
constructor ×1
descriptor ×1
dictionary ×1
factory ×1
getattr ×1
instance ×1
object ×1
oop ×1
plugins ×1
python.net ×1
recursion ×1
struct ×1