标签归档:attributes

类和实例属性之间有什么区别?

问题:类和实例属性之间有什么区别?

之间是否有有意义的区别:

class A(object):
    foo = 5   # some default value

class B(object):
    def __init__(self, foo=5):
        self.foo = foo

如果要创建很多实例,这两种样式在性能或空间要求上是否有差异?阅读代码时,您是否认为两种样式的含义有明显不同?

Is there any meaningful distinction between:

class A(object):
    foo = 5   # some default value

vs.

class B(object):
    def __init__(self, foo=5):
        self.foo = foo

If you’re creating a lot of instances, is there any difference in performance or space requirements for the two styles? When you read the code, do you consider the meaning of the two styles to be significantly different?


回答 0

除了性能方面的考虑之外,还有显着的语义差异。在类属性的情况下,仅引用一个对象。在实例属性设置实例中,可以有多个引用对象。例如

>>> class A: foo = []
>>> a, b = A(), A()
>>> a.foo.append(5)
>>> b.foo
[5]
>>> class A:
...  def __init__(self): self.foo = []
>>> a, b = A(), A()
>>> a.foo.append(5)
>>> b.foo    
[]

Beyond performance considerations, there is a significant semantic difference. In the class attribute case, there is just one object referred to. In the instance-attribute-set-at-instantiation, there can be multiple objects referred to. For instance

>>> class A: foo = []
>>> a, b = A(), A()
>>> a.foo.append(5)
>>> b.foo
[5]
>>> class A:
...  def __init__(self): self.foo = []
>>> a, b = A(), A()
>>> a.foo.append(5)
>>> b.foo    
[]

回答 1

区别在于该类的属性由所有实例共享。实例上的属性对该实例是唯一的。

如果来自C ++,则类的属性更像静态成员变量。

The difference is that the attribute on the class is shared by all instances. The attribute on an instance is unique to that instance.

If coming from C++, attributes on the class are more like static member variables.


回答 2

这是一篇很好的文章,总结如下。

class Bar(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
Bar.class_var
## 1
foo = MyClass(2)

## Finds i_var in foo's instance namespace
foo.i_var
## 2

## Doesn't find class_var in instance namespace…
## So look's in class namespace (Bar.__dict__)
foo.class_var
## 1

并以视觉形式

类属性分配

  • 如果通过访问该类设置了一个类属性,它将覆盖所有实例的值

    foo = Bar(2)
    foo.class_var
    ## 1
    Bar.class_var = 2
    foo.class_var
    ## 2
  • 如果通过访问实例来设置类变量,则它将覆盖该实例的值。实际上,这会覆盖类变量,并将其转变为仅可用于该实例的直观实例变量。

    foo = Bar(2)
    foo.class_var
    ## 1
    foo.class_var = 2
    foo.class_var
    ## 2
    Bar.class_var
    ## 1

什么时候使用class属性?

  • 存储常数。由于可以将类属性作为类本身的属性进行访问,因此最好使用它们来存储类范围的,特定于类的常量

    class Circle(object):
         pi = 3.14159
    
         def __init__(self, radius):
              self.radius = radius   
        def area(self):
             return Circle.pi * self.radius * self.radius
    
    Circle.pi
    ## 3.14159
    c = Circle(10)
    c.pi
    ## 3.14159
    c.area()
    ## 314.159
  • 定义默认值。举一个简单的例子,我们可以创建一个有界列表(即只能容纳一定数量或更少数量元素的列表),并选择默认上限为10个项目

    class MyClass(object):
        limit = 10
    
        def __init__(self):
            self.data = []
        def item(self, i):
            return self.data[i]
    
        def add(self, e):
            if len(self.data) >= self.limit:
                raise Exception("Too many elements")
            self.data.append(e)
    
     MyClass.limit
     ## 10

Here is a very good post, and summary it as below.

class Bar(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
Bar.class_var
## 1
foo = MyClass(2)

## Finds i_var in foo's instance namespace
foo.i_var
## 2

## Doesn't find class_var in instance namespace…
## So look's in class namespace (Bar.__dict__)
foo.class_var
## 1

And in visual form

Class attribute assignment

  • If a class attribute is set by accessing the class, it will override the value for all instances

    foo = Bar(2)
    foo.class_var
    ## 1
    Bar.class_var = 2
    foo.class_var
    ## 2
    
  • If a class variable is set by accessing an instance, it will override the value only for that instance. This essentially overrides the class variable and turns it into an instance variable available, intuitively, only for that instance.

    foo = Bar(2)
    foo.class_var
    ## 1
    foo.class_var = 2
    foo.class_var
    ## 2
    Bar.class_var
    ## 1
    

When would you use class attribute?

  • Storing constants. As class attributes can be accessed as attributes of the class itself, it’s often nice to use them for storing Class-wide, Class-specific constants

    class Circle(object):
         pi = 3.14159
    
         def __init__(self, radius):
              self.radius = radius   
        def area(self):
             return Circle.pi * self.radius * self.radius
    
    Circle.pi
    ## 3.14159
    c = Circle(10)
    c.pi
    ## 3.14159
    c.area()
    ## 314.159
    
  • Defining default values. As a trivial example, we might create a bounded list (i.e., a list that can only hold a certain number of elements or fewer) and choose to have a default cap of 10 items

    class MyClass(object):
        limit = 10
    
        def __init__(self):
            self.data = []
        def item(self, i):
            return self.data[i]
    
        def add(self, e):
            if len(self.data) >= self.limit:
                raise Exception("Too many elements")
            self.data.append(e)
    
     MyClass.limit
     ## 10
    

回答 3

由于此处评论中的人们以及其他两个标记为重复的问题似乎都以相同的方式引起了混淆,因此我认为有必要在Alex Coventry的基础上再增加一个答案。

Alex分配一个可变类型的值(例如列表)的事实与是否共享事物无关。我们可以通过id函数或is运算符看到这一点:

>>> class A: foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
True
>>> class A:
...     def __init__(self): self.foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
False

(如果您想知道为什么我使用object()而不是说,5那是为了避免遇到两个我不想讨论的其他问题;由于两个不同的原因,完全独立创建的5s最终可能是相同的数字实例,5但完全不能单独创建object())。


那么,为什么a.foo.append(5)在Alex的示例中会影响b.foo,但a.foo = 5在我的示例中却没有呢?那么,尝试a.foo = 5在Alex的例子,并注意不影响b.foo两种

a.foo = 5只是a.foo为…而出名5。这不会影响b.foo,也不会影响以前a.foo引用的旧值的任何其他名称。*我们正在创建一个隐藏类属性的实例属性,这有点棘手,但是一旦得到,就没有什么复杂的了发生在这里。


希望现在可以清楚地知道Alex使用列表的原因:您可以对列表进行变异的事实意味着,更容易显示两个变量命名相同的列表,并且这也意味着在现实生活中的代码中更重要的是要知道您是否具有两个列表或同一列表的两个名称。


*对于来自C ++之类的人的困惑在于,在Python中,值不存储在变量中。值本身就存在于值域中,变量只是值的名称,赋值只是为值创建一个新名称。如果有帮助,请将每个Python变量视为shared_ptr<T>而不是T

**有些人通过将class属性用作实例属性的“默认值”来利用此属性,实例属性可以设置也可以不设置。在某些情况下这可能很有用,但也可能造成混淆,因此请谨慎使用。

Since people in the comments here and in two other questions marked as dups all appear to be confused about this in the same way, I think it’s worth adding an additional answer on top of Alex Coventry’s.

The fact that Alex is assigning a value of a mutable type, like a list, has nothing to do with whether things are shared or not. We can see this with the id function or the is operator:

>>> class A: foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
True
>>> class A:
...     def __init__(self): self.foo = object()
>>> a, b = A(), A()
>>> a.foo is b.foo
False

(If you’re wondering why I used object() instead of, say, 5, that’s to avoid running into two whole other issues which I don’t want to get into here; for two different reasons, entirely separately-created 5s can end up being the same instance of the number 5. But entirely separately-created object()s cannot.)


So, why is it that a.foo.append(5) in Alex’s example affects b.foo, but a.foo = 5 in my example doesn’t? Well, try a.foo = 5 in Alex’s example, and notice that it doesn’t affect b.foo there either.

a.foo = 5 is just making a.foo into a name for 5. That doesn’t affect b.foo, or any other name for the old value that a.foo used to refer to.* It’s a little tricky that we’re creating an instance attribute that hides a class attribute,** but once you get that, nothing complicated is happening here.


Hopefully it’s now obvious why Alex used a list: the fact that you can mutate a list means it’s easier to show that two variables name the same list, and also means it’s more important in real-life code to know whether you have two lists or two names for the same list.


* The confusion for people coming from a language like C++ is that in Python, values aren’t stored in variables. Values live off in value-land, on their own, variables are just names for values, and assignment just creates a new name for a value. If it helps, think of each Python variable as a shared_ptr<T> instead of a T.

** Some people take advantage of this by using a class attribute as a “default value” for an instance attribute that instances may or may not set. This can be useful in some cases, but it can also be confusing, so be careful with it.


回答 4

还有另一种情况。

类和实例属性是Descriptor

# -*- encoding: utf-8 -*-


class RevealAccess(object):
    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        return self.val


class Base(object):
    attr_1 = RevealAccess(10, 'var "x"')

    def __init__(self):
        self.attr_2 = RevealAccess(10, 'var "x"')


def main():
    b = Base()
    print("Access to class attribute, return: ", Base.attr_1)
    print("Access to instance attribute, return: ", b.attr_2)

if __name__ == '__main__':
    main()

以上将输出:

('Access to class attribute, return: ', 10)
('Access to instance attribute, return: ', <__main__.RevealAccess object at 0x10184eb50>)

通过类或实例访问相同类型的实例将返回不同的结果!

而且我在c.PyObject_GenericGetAttr定义中找到了一篇不错的文章

说明

如果在组成类的字典中找到该属性。对象MRO,然后检查要查找的属性是否指向数据描述符(这仅是同时实现__get____set__方法的类)。如果是这样,请通过调用__get__数据描述符的方法来解析属性查找(第28-33行)。

There is one more situation.

Class and instance attributes is Descriptor.

# -*- encoding: utf-8 -*-


class RevealAccess(object):
    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        return self.val


class Base(object):
    attr_1 = RevealAccess(10, 'var "x"')

    def __init__(self):
        self.attr_2 = RevealAccess(10, 'var "x"')


def main():
    b = Base()
    print("Access to class attribute, return: ", Base.attr_1)
    print("Access to instance attribute, return: ", b.attr_2)

if __name__ == '__main__':
    main()

Above will output:

('Access to class attribute, return: ', 10)
('Access to instance attribute, return: ', <__main__.RevealAccess object at 0x10184eb50>)

The same type of instance access through class or instance return different result!

And i found in c.PyObject_GenericGetAttr definition,and a great post.

Explain

If the attribute is found in the dictionary of the classes which make up. the objects MRO, then check to see if the attribute being looked up points to a Data Descriptor (which is nothing more that a class implementing both the __get__ and the __set__ methods). If it does, resolve the attribute lookup by calling the __get__ method of the Data Descriptor (lines 28–33).


使用beautifulsoup提取属性值

问题:使用beautifulsoup提取属性值

我试图在网页上的特定“输入”标签中提取单个“值”属性的内容。我使用以下代码:

import urllib
f = urllib.urlopen("http://58.68.130.147")
s = f.read()
f.close()

from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(s)

inputTag = soup.findAll(attrs={"name" : "stainfo"})

output = inputTag['value']

print str(output)

我收到TypeError:列表索引必须是整数,而不是str

即使从Beautifulsoup文档中我了解到字符串在这里也不应该成为问题…但是我没有专家,我可能会误解了。

任何建议,不胜感激!提前致谢。

I am trying to extract the content of a single “value” attribute in a specific “input” tag on a webpage. I use the following code:

import urllib
f = urllib.urlopen("http://58.68.130.147")
s = f.read()
f.close()

from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(s)

inputTag = soup.findAll(attrs={"name" : "stainfo"})

output = inputTag['value']

print str(output)

I get a TypeError: list indices must be integers, not str

even though from the Beautifulsoup documentation i understand that strings should not be a problem here… but i a no specialist and i may have misunderstood.

Any suggestion is greatly appreciated! Thanks in advance.


回答 0

.find_all() 返回所有找到的元素的列表,因此:

input_tag = soup.find_all(attrs={"name" : "stainfo"})

input_tag是一个列表(可能仅包含一个元素)。根据您的确切要求,您应该执行以下任一操作:

 output = input_tag[0]['value']

或使用.find()仅返回一个(第一个)找到的元素的方法:

 input_tag = soup.find(attrs={"name": "stainfo"})
 output = input_tag['value']

.find_all() returns list of all found elements, so:

input_tag = soup.find_all(attrs={"name" : "stainfo"})

input_tag is a list (probably containing only one element). Depending on what you want exactly you either should do:

output = input_tag[0]['value']

or use .find() method which returns only one (first) found element:

input_tag = soup.find(attrs={"name": "stainfo"})
output = input_tag['value']

回答 1

在中Python 3.x,只需get(attr_name)在您使用的标签对象上使用find_all

xmlData = None

with open('conf//test1.xml', 'r') as xmlFile:
    xmlData = xmlFile.read()

xmlDecoded = xmlData

xmlSoup = BeautifulSoup(xmlData, 'html.parser')

repElemList = xmlSoup.find_all('repeatingelement')

for repElem in repElemList:
    print("Processing repElem...")
    repElemID = repElem.get('id')
    repElemName = repElem.get('name')

    print("Attribute id = %s" % repElemID)
    print("Attribute name = %s" % repElemName)

针对如下的XML文件conf//test1.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <singleElement>
        <subElementX>XYZ</subElementX>
    </singleElement>
    <repeatingElement id="11" name="Joe"/>
    <repeatingElement id="12" name="Mary"/>
</root>

印刷品:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary

In Python 3.x, simply use get(attr_name) on your tag object that you get using find_all:

xmlData = None

with open('conf//test1.xml', 'r') as xmlFile:
    xmlData = xmlFile.read()

xmlDecoded = xmlData

xmlSoup = BeautifulSoup(xmlData, 'html.parser')

repElemList = xmlSoup.find_all('repeatingelement')

for repElem in repElemList:
    print("Processing repElem...")
    repElemID = repElem.get('id')
    repElemName = repElem.get('name')

    print("Attribute id = %s" % repElemID)
    print("Attribute name = %s" % repElemName)

against XML file conf//test1.xml that looks like:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <singleElement>
        <subElementX>XYZ</subElementX>
    </singleElement>
    <repeatingElement id="11" name="Joe"/>
    <repeatingElement id="12" name="Mary"/>
</root>

prints:

Processing repElem...
Attribute id = 11
Attribute name = Joe
Processing repElem...
Attribute id = 12
Attribute name = Mary

回答 2

如果要从上面的源中检索属性的多个值,可以使用findAll和列表推导来获取所需的一切:

import urllib
f = urllib.urlopen("http://58.68.130.147")
s = f.read()
f.close()

from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(s)

inputTags = soup.findAll(attrs={"name" : "stainfo"})
### You may be able to do findAll("input", attrs={"name" : "stainfo"})

output = [x["stainfo"] for x in inputTags]

print output
### This will print a list of the values.

If you want to retrieve multiple values of attributes from the source above, you can use findAll and a list comprehension to get everything you need:

import urllib
f = urllib.urlopen("http://58.68.130.147")
s = f.read()
f.close()

from BeautifulSoup import BeautifulStoneSoup
soup = BeautifulStoneSoup(s)

inputTags = soup.findAll(attrs={"name" : "stainfo"})
### You may be able to do findAll("input", attrs={"name" : "stainfo"})

output = [x["stainfo"] for x in inputTags]

print output
### This will print a list of the values.

回答 3

我实际上建议您使用一种节省时间的方法,假设您知道哪种标签具有这些属性。

假设标签xyz的attritube名为“ staininfo”。

full_tag = soup.findAll("xyz")

而且我不希望您知道full_tag是一个列表

for each_tag in full_tag:
    staininfo_attrb_value = each_tag["staininfo"]
    print staininfo_attrb_value

因此,您可以获得所有标签xyz的staininfo的所有attrb值

I would actually suggest you a time saving way to go with this assuming that you know what kind of tags have those attributes.

suppose say a tag xyz has that attritube named “staininfo”..

full_tag = soup.findAll("xyz")

And i wan’t you to understand that full_tag is a list

for each_tag in full_tag:
    staininfo_attrb_value = each_tag["staininfo"]
    print staininfo_attrb_value

Thus you can get all the attrb values of staininfo for all the tags xyz


回答 4

您也可以使用:

import requests
from bs4 import BeautifulSoup
import csv

url = "http://58.68.130.147/"
r = requests.get(url)
data = r.text

soup = BeautifulSoup(data, "html.parser")
get_details = soup.find_all("input", attrs={"name":"stainfo"})

for val in get_details:
    get_val = val["value"]
    print(get_val)

you can also use this :

import requests
from bs4 import BeautifulSoup
import csv

url = "http://58.68.130.147/"
r = requests.get(url)
data = r.text

soup = BeautifulSoup(data, "html.parser")
get_details = soup.find_all("input", attrs={"name":"stainfo"})

for val in get_details:
    get_val = val["value"]
    print(get_val)

回答 5

我在Beautifulsoup 4.8.1中使用它来获取某些元素的所有类属性的值:

from bs4 import BeautifulSoup

html = "<td class='val1'/><td col='1'/><td class='val2' />"

bsoup = BeautifulSoup(html, 'html.parser')

for td in bsoup.find_all('td'):
    if td.has_attr('class'):
        print(td['class'][0])

重要的是要注意,即使属性只有一个值,属性键也会检索列表。

I am using this with Beautifulsoup 4.8.1 to get the value of all class attributes of certain elements:

from bs4 import BeautifulSoup

html = "<td class='val1'/><td col='1'/><td class='val2' />"

bsoup = BeautifulSoup(html, 'html.parser')

for td in bsoup.find_all('td'):
    if td.has_attr('class'):
        print(td['class'][0])

Its important to note that the attribute key retrieves a list even when the attribute has only a single value.


获取类的属性

问题:获取类的属性

我想获取一个类的属性,说:

class MyClass():
  a = "12"
  b = "34"

  def myfunc(self):
    return self.a

使用MyClass.__dict__给了我一系列属性和函数,甚至还有像__module__和的函数__doc__。而MyClass().__dict__除非我显式设置该实例的属性值,否则会给我一个空的字典。

我只想要属性,在上面的示例中,这些属性是:ab

I want to get the attributes of a class, say:

class MyClass():
  a = "12"
  b = "34"

  def myfunc(self):
    return self.a

using MyClass.__dict__ gives me a list of attributes and functions, and even functions like __module__ and __doc__. While MyClass().__dict__ gives me an empty dict unless I explicitly set an attribute value of that instance.

I just want the attributes, in the example above those would be: a and b


回答 0

尝试检查模块。getmembers并且各种测试应该会有所帮助。

编辑:

例如,

class MyClass(object):
    a = '12'
    b = '34'
    def myfunc(self):
        return self.a

>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
 ('__dict__',
  <dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>,
   '__doc__': None,
   '__module__': '__main__',
   '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
   'a': '34',
   'b': '12',
   'myfunc': <function __main__.myfunc>}>),
 ('__doc__', None),
 ('__module__', '__main__'),
 ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
 ('a', '34'),
 ('b', '12')]

现在,特殊的方法和属性引起了我的共鸣-可以通过多种方式处理这些方法和属性,其中最简单的方法就是根据名称进行过滤。

>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]

…,其中更复杂的可以包括特殊的属性名称检查甚至元类;)

Try the inspect module. getmembers and the various tests should be helpful.

EDIT:

For example,

class MyClass(object):
    a = '12'
    b = '34'
    def myfunc(self):
        return self.a

>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
 ('__dict__',
  <dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>,
   '__doc__': None,
   '__module__': '__main__',
   '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
   'a': '34',
   'b': '12',
   'myfunc': <function __main__.myfunc>}>),
 ('__doc__', None),
 ('__module__', '__main__'),
 ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
 ('a', '34'),
 ('b', '12')]

Now, the special methods and attributes get on my nerves- those can be dealt with in a number of ways, the easiest of which is just to filter based on name.

>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]

…and the more complicated of which can include special attribute name checks or even metaclasses ;)


回答 1

def props(cls):   
  return [i for i in cls.__dict__.keys() if i[:1] != '_']

properties = props(MyClass)
def props(cls):   
  return [i for i in cls.__dict__.keys() if i[:1] != '_']

properties = props(MyClass)

回答 2

myfunc 的属性MyClass。这是在运行时发现的方式:

myinstance = MyClass()
myinstance.myfunc()

它在myinstancenamed myfunc上寻找一个属性,找不到一个,发现它myinstance是的一个实例,MyClass并在那里查找。

因此,属性的完整列表MyClass为:

>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']

(请注意,我使用dir只是列出类成员的一种快速简便的方法:它只能以探索的方式使用,而不能在生产代码中使用)

如果您只想要特定的属性,则需要使用一些条件来过滤此列表,因为__doc____module__myfunc没有特殊的以任何方式,他们的属性完全相同的方式ab是。

我从未使用过Matt和Borealid提到的inspect模块,但是从一个简短的链接来看,它似乎具有测试可以帮助您完成此任务,但是您需要编写自己的谓词函数,因为这似乎是您想要的大概是 通过的isroutine测试且不会以两个下划线开头和结尾。

另请注意:通过class MyClass():在python 2.7中使用,您正在使用过时的老式类。除非您是为了与极老的库兼容而故意这样做,否则应将您的类定义为class MyClass(object):。在Python 3中,没有“旧式”类,并且此行为是默认行为。然而,使用newstyle班会帮你很多更多的自动定义的属性:

>>> class MyClass(object):
        a = "12"
        b = "34"
        def myfunc(self):
            return self.a
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'myfunc']

myfunc is an attribute of MyClass. That’s how it’s found when you run:

myinstance = MyClass()
myinstance.myfunc()

It looks for an attribute on myinstance named myfunc, doesn’t find one, sees that myinstance is an instance of MyClass and looks it up there.

So the complete list of attributes for MyClass is:

>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']

(Note that I’m using dir just as a quick and easy way to list the members of the class: it should only be used in an exploratory fashion, not in production code)

If you only want particular attributes, you’ll need to filter this list using some criteria, because __doc__, __module__, and myfunc aren’t special in any way, they’re attributes in exactly the same way that a and b are.

I’ve never used the inspect module referred to by Matt and Borealid, but from a brief link it looks like it has tests to help you do this, but you’ll need to write your own predicate function, since it seems what you want is roughly the attributes that don’t pass the isroutine test and don’t start and end with two underscores.

Also note: by using class MyClass(): in Python 2.7 you’re using the wildly out of date old-style classes. Unless you’re doing so deliberately for compatibility with extremely old libraries, you should be instead defining your class as class MyClass(object):. In Python 3 there are no “old-style” classes, and this behaviour is the default. However, using newstyle classes will get you a lot more automatically defined attributes:

>>> class MyClass(object):
        a = "12"
        b = "34"
        def myfunc(self):
            return self.a
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'myfunc']

回答 3

仅获取实例属性很容易。
但是还要获取类属性没有函数的情况下比较棘手。

仅实例属性

如果您只需要列出实例属性,请使用
for attribute, value in my_instance__dict__items()

>>> from __future__ import (absolute_import, division, print_function)
>>> class MyClass(object):
...   def __init__(self):
...     self.a = 2
...     self.b = 3
...   def print_instance_attributes(self):
...     for attribute, value in self.__dict__.items():
...       print(attribute, '=', value)
...
>>> my_instance = MyClass()
>>> my_instance.print_instance_attributes()
a = 2
b = 3
>>> for attribute, value in my_instance.__dict__.items():
...   print(attribute, '=', value)
...
a = 2
b = 3

实例和类属性

要获得没有功能的类属性,诀窍是使用callable()

静态方法不总是callable

因此,不要使用callable(value)use
callablegetattrMyClass, attribute))

from __future__ import (absolute_import, division, print_function)

class MyClass(object):
   a = "12"
   b = "34"               # class attributes

   def __init__(self, c, d):
     self.c = c
     self.d = d           # instance attributes

   @staticmethod
   def mystatic():        # static method
       return MyClass.b

   def myfunc(self):      # non-static method
     return self.a

   def print_instance_attributes(self):
     print('[instance attributes]')
     for attribute, value in self.__dict__.items():
        print(attribute, '=', value)

   def print_class_attributes(self):
     print('[class attributes]')
     for attribute in self.__dict__.keys():
       if attribute[:2] != '__':
         value = getattr(self, attribute)
         if not callable(value):
           print(attribute, '=', value)

v = MyClass(4,2)
v.print_class_attributes()
v.print_instance_attributes()

注意: print_class_attributes()应该       但不是这个愚蠢和简单@staticmethod
示例中,。

的结果

$ python2 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2

的结果相同

$ python3 ./print_attributes.py
[class attributes]
b = 34
a = 12
[instance attributes]
c = 4
d = 2

Getting only the instance attributes is easy.
But getting also the class attributes without the functions is a bit more tricky.

Instance attributes only

If you only have to list instance attributes just use
for attribute, value in my_instance.__dict__.items()

>>> from __future__ import (absolute_import, division, print_function)
>>> class MyClass(object):
...   def __init__(self):
...     self.a = 2
...     self.b = 3
...   def print_instance_attributes(self):
...     for attribute, value in self.__dict__.items():
...       print(attribute, '=', value)
...
>>> my_instance = MyClass()
>>> my_instance.print_instance_attributes()
a = 2
b = 3
>>> for attribute, value in my_instance.__dict__.items():
...   print(attribute, '=', value)
...
a = 2
b = 3

Instance and class attributes

To get also the class attributes without the functions, the trick is to use callable().

But static methods are not always callable!

Therefore, instead of using callable(value) use
callable(getattr(MyClass, attribute))

Example

from __future__ import (absolute_import, division, print_function)

class MyClass(object):
   a = "12"
   b = "34"               # class attributes

   def __init__(self, c, d):
     self.c = c
     self.d = d           # instance attributes

   @staticmethod
   def mystatic():        # static method
       return MyClass.b

   def myfunc(self):      # non-static method
     return self.a

   def print_instance_attributes(self):
     print('[instance attributes]')
     for attribute, value in self.__dict__.items():
        print(attribute, '=', value)

   def print_class_attributes(self):
     print('[class attributes]')
     for attribute in self.__dict__.keys():
       if attribute[:2] != '__':
         value = getattr(self, attribute)
         if not callable(value):
           print(attribute, '=', value)

v = MyClass(4,2)
v.print_class_attributes()
v.print_instance_attributes()

Note: print_class_attributes() should be @staticmethod
      but not in this stupid and simple example.

Result for

$ python2 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2

Same result for

$ python3 ./print_attributes.py
[class attributes]
b = 34
a = 12
[instance attributes]
c = 4
d = 2

回答 4

MyClass().__class__.__dict__

但是,这样做的“正确”是通过检查模块

MyClass().__class__.__dict__

However, the “right” was to do this is via the inspect module.


回答 5

import re

class MyClass:
    a = "12"
    b = "34"

    def myfunc(self):
        return self.a

attributes = [a for a, v in MyClass.__dict__.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]

对于MyClass的实例,例如

mc = MyClass()

用于type(mc)代替MyClass列表理解。但是,如果将一个属性动态添加到mc,例如mc.c = "42",则type(mc)在此策略中使用该属性时将不会显示该属性。它仅提供原始类的属性。

要获得类实例的完整字典,您需要将type(mc).__dict__和的字典合并mc.__dict__

mc = MyClass()
mc.c = "42"

# Python 3.5
combined_dict = {**type(mc).__dict__, **mc.__dict__}

# Or Python < 3.5
def dict_union(d1, d2):
    z = d1.copy()
    z.update(d2)
    return z

combined_dict = dict_union(type(mc).__dict__, mc.__dict__)

attributes = [a for a, v in combined_dict.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]
import re

class MyClass:
    a = "12"
    b = "34"

    def myfunc(self):
        return self.a

attributes = [a for a, v in MyClass.__dict__.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]

For an instance of MyClass, such as

mc = MyClass()

use type(mc) in place of MyClass in the list comprehension. However, if one dynamically adds an attribute to mc, such as mc.c = "42", the attribute won’t show up when using type(mc) in this strategy. It only gives the attributes of the original class.

To get the complete dictionary for a class instance, you would need to COMBINE the dictionaries of type(mc).__dict__ and mc.__dict__.

mc = MyClass()
mc.c = "42"

# Python 3.5
combined_dict = {**type(mc).__dict__, **mc.__dict__}

# Or Python < 3.5
def dict_union(d1, d2):
    z = d1.copy()
    z.update(d2)
    return z

combined_dict = dict_union(type(mc).__dict__, mc.__dict__)

attributes = [a for a, v in combined_dict.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]

回答 6

我不知道是否已经做过类似的事情,但是我使用vars()做了一个不错的属性搜索功能。vars()创建您通过其传递的类的属性的字典。

class Player():
    def __init__(self):
        self.name = 'Bob'
        self.age = 36
        self.gender = 'Male'

s = vars(Player())
#From this point if you want to print all the attributes, just do print(s)

#If the class has a lot of attributes and you want to be able to pick 1 to see
#run this function
def play():
    ask = input("What Attribute?>: ")
    for key, value in s.items():
        if key == ask:
            print("self.{} = {}".format(key, value))
            break
    else:
        print("Couldn't find an attribute for self.{}".format(ask))

我正在用Python开发大量的Text Adventure,到目前为止,我的Player类具有100多个属性。我用它来搜索需要查看的特定属性。

I don’t know if something similar has been made by now or not, but I made a nice attribute search function using vars(). vars() creates a dictionary of the attributes of a class you pass through it.

class Player():
    def __init__(self):
        self.name = 'Bob'
        self.age = 36
        self.gender = 'Male'

s = vars(Player())
#From this point if you want to print all the attributes, just do print(s)

#If the class has a lot of attributes and you want to be able to pick 1 to see
#run this function
def play():
    ask = input("What Attribute?>: ")
    for key, value in s.items():
        if key == ask:
            print("self.{} = {}".format(key, value))
            break
    else:
        print("Couldn't find an attribute for self.{}".format(ask))

I’m developing a pretty massive Text Adventure in Python, my Player class so far has over 100 attributes. I use this to search for specific attributes I need to see.


回答 7

我想这可以在没有检查的情况下完成。

参加以下类:

 class Test:
   a = 1
   b = 2

   def __init__(self):
     self.c = 42

   @staticmethod
   def toto():
     return "toto"

   def test(self):
     return "test"

查看成员及其类型:

t = Test()
l = [ (x, eval('type(x.%s).__name__' % x)) for x in dir(a) ]

…给出:

[('__doc__', 'NoneType'),
 ('__init__', 'instancemethod'),
 ('__module__', 'str'),
 ('a', 'int'),
 ('b', 'int'),
 ('c', 'int'),
 ('test', 'instancemethod'),
 ('toto', 'function')]

因此,仅输出变量,您只需按类型过滤结果,并且名称不能以“ __”开头。例如

filter(lambda x: x[1] not in ['instancemethod', 'function'] and not x[0].startswith('__'), l)

[('a', 'int'), ('b', 'int'), ('c', 'int')] # actual result

而已。

注意:如果您使用的是Python 3,请将迭代器转换为列表。

如果您想要一种更强大的方法,请使用inspect

This can be done without inspect, I guess.

Take the following class:

 class Test:
   a = 1
   b = 2

   def __init__(self):
     self.c = 42

   @staticmethod
   def toto():
     return "toto"

   def test(self):
     return "test"

Looking at the members along with their types:

t = Test()
l = [ (x, eval('type(x.%s).__name__' % x)) for x in dir(a) ]

… gives:

[('__doc__', 'NoneType'),
 ('__init__', 'instancemethod'),
 ('__module__', 'str'),
 ('a', 'int'),
 ('b', 'int'),
 ('c', 'int'),
 ('test', 'instancemethod'),
 ('toto', 'function')]

So to output only the variables, you just have to filter the results by type, and names not starting with ‘__’. E.g.

filter(lambda x: x[1] not in ['instancemethod', 'function'] and not x[0].startswith('__'), l)

[('a', 'int'), ('b', 'int'), ('c', 'int')] # actual result

That’s it.

Note: if you’re using Python 3, convert the iterators to lists.

If you want a more robust way to do it, use inspect.


回答 8

Python 2和3,Whitout导入,通过对象地址过滤对象

简短的解决方案:

返回dict {attribute_name:attribute_value},对象已过滤。即{'a': 1, 'b': (2, 2), 'c': [3, 3]}

{k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}

返回列表[attribute_names],对象已过滤。即['a', 'b', 'c', 'd']

[k for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]

返回列表[attribute_values],对象已过滤。即[1, (2, 2), [3, 3], {4: 4}]

[val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]

不过滤对象

消除if条件。返回{'a': 1, 'c': [3, 3], 'b': (2, 2), 'e': <function <lambda> at 0x7fc8a870fd70>, 'd': {4: 4}, 'f': <object object at 0x7fc8abe130e0>}

{k: val for k, val in self.__dict__.items()}

长期解决

只要的默认实现__repr__不被覆盖if语句将返回True如果位置在记忆的十六进制表示val是在__repr__返回的字符串。

关于默认实现,__repr__您可以找到此答案有用。简而言之:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Wich返回类似以下的字符串:

<__main__.Bar object at 0x7f3373be5998>

通过该id()方法可以获取每个元素在内存中的位置。

Python文档对id()说:

返回对象的“身份”。这是一个整数,可以保证在此对象的生存期内唯一且恒定。具有不重叠生存期的两个对象可能具有相同的id()值。

CPython实现细节:这是对象在内存中的地址。


自己尝试

class Bar:

    def __init__(self):

        self.a = 1
        self.b = (2, 2)
        self.c = [3, 3]
        self.d = {4: 4}
        self.e = lambda: "5"
        self.f = object()

    #__str__ or __repr__ as you prefer
    def __str__(self):
        return "{}".format(

            # Solution in Short Number 1
            {k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}

        )

# Main
print(Bar())

输出:

{'a': 1, 'c': [3, 3], 'b': (2, 2), 'd': {4: 4}}

注意事项

  • 经过Python 2.7.13和Python 测试3.5.3

  • 在Python 2.x .iteritems()中,优先于.items()

Python 2 & 3, whitout imports, filtering objects by their address

Solutions in short:

Return dict {attribute_name: attribute_value}, objects filtered. i.e {'a': 1, 'b': (2, 2), 'c': [3, 3]}

{k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}

Return list [attribute_names], objects filtered. i.e ['a', 'b', 'c', 'd']

[k for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]

Return list [attribute_values], objects filtered. i.e [1, (2, 2), [3, 3], {4: 4}]

[val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]

Not filtering objects

Removing the if condition. Return {'a': 1, 'c': [3, 3], 'b': (2, 2), 'e': <function <lambda> at 0x7fc8a870fd70>, 'd': {4: 4}, 'f': <object object at 0x7fc8abe130e0>}

{k: val for k, val in self.__dict__.items()}

Solution in long

As long as the default implementation of __repr__ is not overridden the if statement will return True if the hexadecimal representation of the location in memory of val is in the __repr__ return string.

Regarding the default implementation of __repr__ you could find useful this answer. In short:

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Wich returns a string like:

<__main__.Bar object at 0x7f3373be5998>

The location in memory of each element is got via the id() method.

Python Docs says about id():

Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

CPython implementation detail: This is the address of the object in memory.


Try by yourself

class Bar:

    def __init__(self):

        self.a = 1
        self.b = (2, 2)
        self.c = [3, 3]
        self.d = {4: 4}
        self.e = lambda: "5"
        self.f = object()

    #__str__ or __repr__ as you prefer
    def __str__(self):
        return "{}".format(

            # Solution in Short Number 1
            {k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}

        )

# Main
print(Bar())

Output:

{'a': 1, 'c': [3, 3], 'b': (2, 2), 'd': {4: 4}}

Note:

  • Tested with Python 2.7.13 and Python 3.5.3

  • In Python 2.x .iteritems() is preferred over .items()


回答 9

我最近需要弄清楚与该问题类似的内容,因此我想发布一些背景信息,这些信息可能会对将来面对相同问题的其他人有所帮助。

以下是它在Python中的工作方式(来自https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy):

MyClass是类对象,MyClass()是类对象的实例。实例__dict__仅具有特定于该实例的属性和方法(例如self.somethings)。如果属性或方法是类的一部分,则它在类的中__dict__。当您执行时MyClass().__dict__,会建立的实例,MyClass除了类别属性外,没有其他属性或方法,因此为空__dict__

因此,如果您说的话print(MyClass().b),Python首先检查新实例的字典MyClass().__dict__['b'],但找不到b。然后,它检查该类MyClass.__dict__['b']并找到b

这就是为什么您需要该inspect模块来模拟相同的搜索过程。

I recently needed to figure out something similar to this question, so I wanted to post some background info that might be helpful to others facing the same in future.

Here’s how it works in Python (from https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy):

MyClass is a class object, MyClass() is an instance of the class object. An instance’s __dict__ only hold attributes and methods specific to that instance (e.g. self.somethings). If an attribute or method is part of a class, it is in the class’s __dict__. When you do MyClass().__dict__, an instance of MyClass is created with no attributes or methods besides the class attributes, thus the empty __dict__

So if you say print(MyClass().b), Python first checks the new instance’s dict MyClass().__dict__['b'] and fails to find b. It then checks the class MyClass.__dict__['b'] and finds b.

That’s why you need the inspect module, to emulate that same search process.


回答 10

您可以dir()列表推导中使用以获取属性名称:

names = [p for p in dir(myobj) if not p.startswith('_')]

使用getattr()来获得属性本身:

attrs = [getattr(myobj, p) for p in dir(myobj) if not p.startswith('_')]

You can use dir() in a list comprehension to get the attribute names:

names = [p for p in dir(myobj) if not p.startswith('_')]

Use getattr() to get the attributes themselves:

attrs = [getattr(myobj, p) for p in dir(myobj) if not p.startswith('_')]

回答 11

我的解决方案,以获取类的所有属性(而不是方法)(如果该类的文档字符串正确书写,并且属性清楚地说明了):

def get_class_attrs(cls):
    return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])

这一部分cls.__dict__['__doc__']提取了该类的文档字符串。

My solution to get all attributes (not methods) of a class (if the class has a properly written docstring that has the attributes clearly spelled out):

def get_class_attrs(cls):
    return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])

This piece cls.__dict__['__doc__'] extracts the docstring of the class.


回答 12

为什么需要列出属性?从语义上看,您的类是一个集合。在这种情况下,我建议使用枚举:

import enum

class myClass(enum.Enum):
     a = "12"
     b = "34"

列出您的属性?没有比这更容易的了:

for attr in myClass:
    print("Name / Value:", attr.name, attr.value)

Why do you need to list the attributes? Seems that semantically your class is a collection. In this cases I recommend to use enum:

import enum

class myClass(enum.Enum):
     a = "12"
     b = "34"

List your attributes? Nothing easier than this:

for attr in myClass:
    print("Name / Value:", attr.name, attr.value)

回答 13

如果要“获取”属性,则有一个非常简单的答案,该答案应该很明显:getattr

class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
    return self.a

>>> getattr(MyClass, 'a')
'12'

>>> getattr(MyClass, 'myfunc')
<function MyClass.myfunc at 0x10de45378>

它在python 2.7和python 3.x中都很好用。

如果要列出这些项目,则仍然需要使用inspect。

If you want to “get” an attribute, there is a very simple answer, which should be obvious: getattr

class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
    return self.a

>>> getattr(MyClass, 'a')
'12'

>>> getattr(MyClass, 'myfunc')
<function MyClass.myfunc at 0x10de45378>

It works dandy both in Python 2.7 and Python 3.x.

If you want a list of these items, you will still need to use inspect.


回答 14

两个功能:

def get_class_attr(Cls) -> []:
    import re
    return [a for a, v in Cls.__dict__.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]

def get_class_attr_val(cls):
    attr = get_class_attr(type(cls))
    attr_dict = {}
    for a in attr:
        attr_dict[a] = getattr(cls, a)
    return attr_dict

用:

>>> class MyClass:
    a = "12"
    b = "34"
    def myfunc(self):
        return self.a

>>> m = MyClass()
>>> get_class_attr_val(m)
{'a': '12', 'b': '34'}

two function:

def get_class_attr(Cls) -> []:
    import re
    return [a for a, v in Cls.__dict__.items()
              if not re.match('<function.*?>', str(v))
              and not (a.startswith('__') and a.endswith('__'))]

def get_class_attr_val(cls):
    attr = get_class_attr(type(cls))
    attr_dict = {}
    for a in attr:
        attr_dict[a] = getattr(cls, a)
    return attr_dict

use:

>>> class MyClass:
    a = "12"
    b = "34"
    def myfunc(self):
        return self.a

>>> m = MyClass()
>>> get_class_attr_val(m)
{'a': '12', 'b': '34'}

回答 15

以下是我想要的。

测试数据

class Base:
    b = 'b'


class MyClass(Base):
    a = '12'

    def __init__(self, name):
        self.name = name

    @classmethod
    def c(cls):
        ...

    @property
    def p(self):
        return self.a

    def my_fun(self):
        return self.name
print([name for name, val in inspect.getmembers(MyClass) if not name.startswith('_') and not callable(val)])  # need `import inspect`
print([_ for _ in dir(MyClass) if not _.startswith('_') and not callable(getattr(MyClass, _))])
# both are equ: ['a', 'b', 'p']

my_instance = MyClass('c')
print([_ for _ in dir(my_instance) if not _.startswith('_') and not callable(getattr(my_instance, _))])
# ['a', 'b', 'name', 'p']

The following is what I want.

Test Data

class Base:
    b = 'b'


class MyClass(Base):
    a = '12'

    def __init__(self, name):
        self.name = name

    @classmethod
    def c(cls):
        ...

    @property
    def p(self):
        return self.a

    def my_fun(self):
        return self.name
print([name for name, val in inspect.getmembers(MyClass) if not name.startswith('_') and not callable(val)])  # need `import inspect`
print([_ for _ in dir(MyClass) if not _.startswith('_') and not callable(getattr(MyClass, _))])
# both are equ: ['a', 'b', 'p']

my_instance = MyClass('c')
print([_ for _ in dir(my_instance) if not _.startswith('_') and not callable(getattr(my_instance, _))])
# ['a', 'b', 'name', 'p']

回答 16

我知道这是三年前的事,但对于那些将来遇到这个问题的人来说,对我来说:

class_name.attribute 

效果很好。

I know this was three years ago, but for those who are to come by this question in the future, for me:

class_name.attribute 

works just fine.


回答 17

您可以使用MyClass.__attrs__。它只是给出了该类的所有属性。而已。

You can use MyClass.__attrs__. It just gives all the attributes of that class. Nothing more.


检查对象列表是否包含具有特定属性值的对象

问题:检查对象列表是否包含具有特定属性值的对象

我想检查对象列表是否包含具有特定属性值的对象。

class Test:
    def __init__(self, name):
        self.name = name

# in main()
l = []
l.append(Test("t1"))
l.append(Test("t2"))
l.append(Test("t2"))

我想要一种检查列表是否包含名称的对象的方法"t1"。如何做呢?我发现https://stackoverflow.com/a/598415/292291

[x for x in myList if x.n == 30]               # list of all matches
any(x.n == 30 for x in myList)                 # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30]  # indices of all matches

def first(iterable, default=None):
    for item in iterable:
        return item
    return default

first(x for x in myList if x.n == 30)          # the first match, if any

我不想每次都遍历整个列表,我只需要知道是否有1个匹配的实例即可。会first(...)还是any(...)会这样做?

I want to check if my list of objects contain an object with a certain attribute value.

class Test:
    def __init__(self, name):
        self.name = name

# in main()
l = []
l.append(Test("t1"))
l.append(Test("t2"))
l.append(Test("t2"))

I want a way of checking if list contains an object with name "t1" for example. How can it be done? I found https://stackoverflow.com/a/598415/292291,

[x for x in myList if x.n == 30]               # list of all matches
any(x.n == 30 for x in myList)                 # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30]  # indices of all matches

def first(iterable, default=None):
    for item in iterable:
        return item
    return default

first(x for x in myList if x.n == 30)          # the first match, if any

I don’t want to go through the whole list every time, I just need to know if there’s 1 instance which matches. Will first(...) or any(...) or something else do that?


回答 0

文档中您可以很容易地看到,一旦找到匹配项,该any()函数True就会使返回短路。

any(x.name == "t2" for x in l)

As you can easily see from the documentation, the any() function short-circuits an returns True as soon as a match has been found.

any(x.name == "t2" for x in l)

在python中从字典设置属性

问题:在python中从字典设置属性

是否可以通过python中的字典创建对象,使得每个键都是该对象的属性?

像这样:

 d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

 e = Employee(d) 
 print e.name # Oscar 
 print e.age + 10 # 42 

我认为这与该问题几乎完全相反:来自对象字段的Python字典

Is it possible to create an object from a dictionary in python in such a way that each key is an attribute of that object?

Something like this:

 d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

 e = Employee(d) 
 print e.name # Oscar 
 print e.age + 10 # 42 

I think it would be pretty much the inverse of this question: Python dictionary from an object’s fields


回答 0

当然,是这样的:

class Employee(object):
    def __init__(self, initial_data):
        for key in initial_data:
            setattr(self, key, initial_data[key])

更新资料

正如布伦特·纳什(Brent Nash)所建议的,您还可以通过允许使用关键字参数来使其更加灵活:

class Employee(object):
    def __init__(self, *initial_data, **kwargs):
        for dictionary in initial_data:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])

然后您可以这样称呼它:

e = Employee({"name": "abc", "age": 32})

或像这样:

e = Employee(name="abc", age=32)

甚至像这样:

employee_template = {"role": "minion"}
e = Employee(employee_template, name="abc", age=32)

Sure, something like this:

class Employee(object):
    def __init__(self, initial_data):
        for key in initial_data:
            setattr(self, key, initial_data[key])

Update

As Brent Nash suggests, you can make this more flexible by allowing keyword arguments as well:

class Employee(object):
    def __init__(self, *initial_data, **kwargs):
        for dictionary in initial_data:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])

Then you can call it like this:

e = Employee({"name": "abc", "age": 32})

or like this:

e = Employee(name="abc", age=32)

or even like this:

employee_template = {"role": "minion"}
e = Employee(employee_template, name="abc", age=32)

回答 1

以这种方式设置属性几乎肯定不是解决问题的最佳方法。要么:

  1. 您知道所有字段都应该提前。在这种情况下,您可以显式设置所有属性。这看起来像

    class Employee(object):
        def __init__(self, name, last_name, age):
            self.name = name
            self.last_name = last_name
            self.age = age
    
    d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
    e = Employee(**d) 
    
    print e.name # Oscar 
    print e.age + 10 # 42 

    要么

  2. 您不知道所有字段都应该提前。在这种情况下,您应该将数据存储为dict,而不是污染对象命名空间。这些属性用于静态访问。这种情况看起来像

    class Employee(object):
        def __init__(self, data):
            self.data = data
    
    d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
    e = Employee(d) 
    
    print e.data['name'] # Oscar 
    print e.data['age'] + 10 # 42 

与情况1基本等效的另一种解决方案是使用collections.namedtuple。有关如何实现的信息,请参见van的答案。

Setting attributes in this way is almost certainly not the best way to solve a problem. Either:

  1. You know what all the fields should be ahead of time. In that case, you can set all the attributes explicitly. This would look like

    class Employee(object):
        def __init__(self, name, last_name, age):
            self.name = name
            self.last_name = last_name
            self.age = age
    
    d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
    e = Employee(**d) 
    
    print e.name # Oscar 
    print e.age + 10 # 42 
    

    or

  2. You don’t know what all the fields should be ahead of time. In this case, you should store the data as a dict instead of polluting an objects namespace. Attributes are for static access. This case would look like

    class Employee(object):
        def __init__(self, data):
            self.data = data
    
    d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 }
    e = Employee(d) 
    
    print e.data['name'] # Oscar 
    print e.data['age'] + 10 # 42 
    

Another solution that is basically equivalent to case 1 is to use a collections.namedtuple. See van’s answer for how to implement that.


回答 2

您可以使用访问对象的属性__dict__,并对其调用update方法:

>>> class Employee(object):
...     def __init__(self, _dict):
...         self.__dict__.update(_dict)
... 


>>> dict = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

>>> e = Employee(dict)

>>> e.name
'Oscar'

>>> e.age
32

You can access the attributes of an object with __dict__, and call the update method on it:

>>> class Employee(object):
...     def __init__(self, _dict):
...         self.__dict__.update(_dict)
... 


>>> dict = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

>>> e = Employee(dict)

>>> e.name
'Oscar'

>>> e.age
32

回答 3

为什么不只使用属性名称作为字典的键?

class StructMyDict(dict):

     def __getattr__(self, name):
         try:
             return self[name]
         except KeyError as e:
             raise AttributeError(e)

     def __setattr__(self, name, value):
         self[name] = value

您可以使用命名参数,元组列表,字典或单独的属性分配进行初始化,例如:

nautical = StructMyDict(left = "Port", right = "Starboard") # named args

nautical2 = StructMyDict({"left":"Port","right":"Starboard"}) # dictionary

nautical3 = StructMyDict([("left","Port"),("right","Starboard")]) # tuples list

nautical4 = StructMyDict()  # fields TBD
nautical4.left = "Port"
nautical4.right = "Starboard"

for x in [nautical, nautical2, nautical3, nautical4]:
    print "%s <--> %s" % (x.left,x.right)

或者,您可以为未知值返回None,而不是引发属性错误。(web2py存储类中使用的一个技巧)

Why not just use attribute names as keys to a dictionary?

class StructMyDict(dict):

     def __getattr__(self, name):
         try:
             return self[name]
         except KeyError as e:
             raise AttributeError(e)

     def __setattr__(self, name, value):
         self[name] = value

You can initialize with named arguments, a list of tuples, or a dictionary, or individual attribute assignments, e.g.:

nautical = StructMyDict(left = "Port", right = "Starboard") # named args

nautical2 = StructMyDict({"left":"Port","right":"Starboard"}) # dictionary

nautical3 = StructMyDict([("left","Port"),("right","Starboard")]) # tuples list

nautical4 = StructMyDict()  # fields TBD
nautical4.left = "Port"
nautical4.right = "Starboard"

for x in [nautical, nautical2, nautical3, nautical4]:
    print "%s <--> %s" % (x.left,x.right)

Alternatively, instead of raising the attribute error, you can return None for unknown values. (A trick used in the web2py storage class)


回答 4

我认为,settattr如果您确实需要支持,那么使用答案是可行的方法dict

但是,如果Employeeobject只是可以使用点语法(.name)而不是dict语法(['name'])访问的结构,则可以使用namedtuple,如下所示:

from collections import namedtuple

Employee = namedtuple('Employee', 'name age')
e = Employee('noname01', 6)
print e
#>> Employee(name='noname01', age=6)

# create Employee from dictionary
d = {'name': 'noname02', 'age': 7}
e = Employee(**d)
print e
#>> Employee(name='noname02', age=7)
print e._asdict()
#>> {'age': 7, 'name': 'noname02'}

您确实具有_asdict()将所有属性作为字典访问的方法,但是以后只能在构造过程中才能添加其他属性。

I think that answer using settattr are the way to go if you really need to support dict.

But if Employee object is just a structure which you can access with dot syntax (.name) instead of dict syntax (['name']), you can use namedtuple like this:

from collections import namedtuple

Employee = namedtuple('Employee', 'name age')
e = Employee('noname01', 6)
print e
#>> Employee(name='noname01', age=6)

# create Employee from dictionary
d = {'name': 'noname02', 'age': 7}
e = Employee(**d)
print e
#>> Employee(name='noname02', age=7)
print e._asdict()
#>> {'age': 7, 'name': 'noname02'}

You do have _asdict() method to access all properties as dictionary, but you cannot add additional attributes later, only during the construction.


回答 5

例如说

class A():
    def __init__(self):
        self.x=7
        self.y=8
        self.z="name"

如果您想一次设置属性

d = {'x':100,'y':300,'z':"blah"}
a = A()
a.__dict__.update(d)

say for example

class A():
    def __init__(self):
        self.x=7
        self.y=8
        self.z="name"

if you want to set the attributes at once

d = {'x':100,'y':300,'z':"blah"}
a = A()
a.__dict__.update(d)

回答 6

与使用dict类似,您可以像这样使用kwargs:

class Person:
   def __init__(self, **kwargs):
       self.properties = kwargs

   def get_property(self, key):
       return self.properties.get(key, None)

   def main():
       timmy = Person(color = 'red')
       print(timmy.get_property('color')) #prints 'red'

similar to using a dict, you could just use kwargs like so:

class Person:
   def __init__(self, **kwargs):
       self.properties = kwargs

   def get_property(self, key):
       return self.properties.get(key, None)

   def main():
       timmy = Person(color = 'red')
       print(timmy.get_property('color')) #prints 'red'

遍历python中的对象属性

问题:遍历python中的对象属性

我有一个带有几个属性和方法的python对象。我想遍历对象属性。

class my_python_obj(object):
    attr1='a'
    attr2='b'
    attr3='c'

    def method1(self, etc, etc):
        #Statements

我想生成一个包含所有对象属性及其当前值的字典,但是我想以一种动态的方式进行操作(因此,如果以后添加另一个属性,我也不必记住要更新我的函数)。

在php中,变量可以用作键,但是python中的对象是不可写的,如果我为此使用点符号,则会创建一个新属性,其名称为var,这不是我的意图。

为了使事情更清楚:

def to_dict(self):
    '''this is what I already have'''
    d={}
    d["attr1"]= self.attr1
    d["attr2"]= self.attr2
    d["attr3"]= self.attr3
    return d

·

def to_dict(self):
    '''this is what I want to do'''
    d={}
    for v in my_python_obj.attributes:
        d[v] = self.v
    return d

更新:对于属性,我的意思是仅此对象的变量,而不是方法。

I have a python object with several attributes and methods. I want to iterate over object attributes.

class my_python_obj(object):
    attr1='a'
    attr2='b'
    attr3='c'

    def method1(self, etc, etc):
        #Statements

I want to generate a dictionary containing all of the objects attributes and their current values, but I want to do it in a dynamic way (so if later I add another attribute I don’t have to remember to update my function as well).

In php variables can be used as keys, but objects in python are unsuscriptable and if I use the dot notation for this it creates a new attribute with the name of my var, which is not my intent.

Just to make things clearer:

def to_dict(self):
    '''this is what I already have'''
    d={}
    d["attr1"]= self.attr1
    d["attr2"]= self.attr2
    d["attr3"]= self.attr3
    return d

·

def to_dict(self):
    '''this is what I want to do'''
    d={}
    for v in my_python_obj.attributes:
        d[v] = self.v
    return d

Update: With attributes I mean only the variables of this object, not the methods.


回答 0

假设您有一个诸如

>>> class Cls(object):
...     foo = 1
...     bar = 'hello'
...     def func(self):
...         return 'call me'
...
>>> obj = Cls()

调用dir该对象会返回该对象的所有属性,包括python特殊属性。尽管某些对象属性是可调用的,例如方法。

>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo', 'func']

您始终可以使用列表理解来过滤掉特殊方法。

>>> [a for a in dir(obj) if not a.startswith('__')]
['bar', 'foo', 'func']

或者您更喜欢地图/过滤器。

>>> filter(lambda a: not a.startswith('__'), dir(obj))
['bar', 'foo', 'func']

如果要过滤掉这些方法,可以使用内置函数callable作为检查。

>>> [a for a in dir(obj) if not a.startswith('__') and not callable(getattr(obj, a))]
['bar', 'foo']

您还可以使用检查类及其实例对象之间的差异。

>>> set(dir(Cls)) - set(dir(object))
set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__'])

Assuming you have a class such as

>>> class Cls(object):
...     foo = 1
...     bar = 'hello'
...     def func(self):
...         return 'call me'
...
>>> obj = Cls()

calling dir on the object gives you back all the attributes of that object, including python special attributes. Although some object attributes are callable, such as methods.

>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'foo', 'func']

You can always filter out the special methods by using a list comprehension.

>>> [a for a in dir(obj) if not a.startswith('__')]
['bar', 'foo', 'func']

or if you prefer map/filters.

>>> filter(lambda a: not a.startswith('__'), dir(obj))
['bar', 'foo', 'func']

If you want to filter out the methods, you can use the builtin callable as a check.

>>> [a for a in dir(obj) if not a.startswith('__') and not callable(getattr(obj, a))]
['bar', 'foo']

You could also inspect the difference between your class and its instance object using.

>>> set(dir(Cls)) - set(dir(object))
set(['__module__', 'bar', 'func', '__dict__', 'foo', '__weakref__'])

回答 1

通常,__iter__在您的类中放置一个方法并遍历对象属性,或者将此mixin类放入您的类中。

class IterMixin(object):
    def __iter__(self):
        for attr, value in self.__dict__.iteritems():
            yield attr, value

你的班:

>>> class YourClass(IterMixin): pass
...
>>> yc = YourClass()
>>> yc.one = range(15)
>>> yc.two = 'test'
>>> dict(yc)
{'one': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 'two': 'test'}

in general put a __iter__ method in your class and iterate through the object attributes or put this mixin class in your class.

class IterMixin(object):
    def __iter__(self):
        for attr, value in self.__dict__.iteritems():
            yield attr, value

Your class:

>>> class YourClass(IterMixin): pass
...
>>> yc = YourClass()
>>> yc.one = range(15)
>>> yc.two = 'test'
>>> dict(yc)
{'one': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 'two': 'test'}

回答 2

正如已经在一些答案/评论中提到的那样,Python对象已经存储了其属性的字典(不包括方法)。可以通过进行访问__dict__,但是更好的方法是使用vars(尽管输出是相同的)。请注意,修改此字典将修改实例的属性!这可能很有用,但也意味着您应该谨慎使用此字典。这是一个简单的例子:

class A():
    def __init__(self, x=3, y=2, z=5):
        self.x = x
        self._y = y
        self.__z__ = z

    def f(self):
        pass

a = A()
print(vars(a))
# {'x': 3, '_y': 2, '__z__': 5}
# all of the attributes of `a` but no methods!

# note how the dictionary is always up-to-date
a.x = 10
print(vars(a))
# {'x': 10, '_y': 2, '__z__': 5}

# modifying the dictionary modifies the instance attribute
vars(a)["_y"] = 20
print(vars(a))
# {'x': 10, '_y': 20, '__z__': 5}

使用这个dir(a)方法很奇怪,即使不是完全不好,也可以解决这个问题。如果您确实需要遍历该类的所有属性和方法(包括诸如的特殊方法__init__),那是很好的。但是,这似乎不是您想要的,甚至不是您所接受的答案通过使用一些易碎的过滤来尝试删除方法并仅保留属性。您会看到A上面定义的类将如何失败。

__dict__已经在几个答案中使用,但是它们都定义了不必要的方法,而不是直接使用它。只有注释建议使用vars)。

As mentioned in some of the answers/comments already, Python objects already store a dictionary of their attributes (methods aren’t included). This can be accessed as __dict__, but the better way is to use vars (the output is the same, though). Note that modifying this dictionary will modify the attributes on the instance! This can be useful, but also means you should be careful with how you use this dictionary. Here’s a quick example:

class A():
    def __init__(self, x=3, y=2, z=5):
        self.x = x
        self._y = y
        self.__z__ = z

    def f(self):
        pass

a = A()
print(vars(a))
# {'x': 3, '_y': 2, '__z__': 5}
# all of the attributes of `a` but no methods!

# note how the dictionary is always up-to-date
a.x = 10
print(vars(a))
# {'x': 10, '_y': 2, '__z__': 5}

# modifying the dictionary modifies the instance attribute
vars(a)["_y"] = 20
print(vars(a))
# {'x': 10, '_y': 20, '__z__': 5}

Using dir(a) is an odd, if not outright bad, approach to this problem. It’s good if you really needed to iterate over all attributes and methods of the class (including the special methods like __init__). However, this doesn’t seem to be what you want, and even the accepted answer goes about this poorly by applying some brittle filtering to try to remove methods and leave just the attributes; you can see how this would fail for the class A defined above.

(using __dict__ has been done in a couple of answers, but they all define unnecessary methods instead of using it directly. Only a comment suggests to use vars).


回答 3

python中的对象将它们的属性(包括函数)存储在称为的字典中__dict__。您可以(但通常不应该)使用它直接访问属性。如果您只想要一个列表,也可以调用dir(obj),它返回带有所有属性名称的Iterable,然后可以将其传递给getattr

但是,需要对变量名称做任何事情通常都是不好的设计。为什么不将它们保存在集合中?

class Foo(object):
    def __init__(self, **values):
        self.special_values = values

然后,您可以使用 for key in obj.special_values:

Objects in python store their atributes (including functions) in a dict called __dict__. You can (but generally shouldn’t) use this to access the attributes directly. If you just want a list, you can also call dir(obj), which returns an iterable with all the attribute names, which you could then pass to getattr.

However, needing to do anything with the names of the variables is usually bad design. Why not keep them in a collection?

class Foo(object):
    def __init__(self, **values):
        self.special_values = values

You can then iterate over the keys with for key in obj.special_values:


回答 4

class someclass:
        x=1
        y=2
        z=3
        def __init__(self):
           self.current_idx = 0
           self.items = ["x","y","z"]
        def next(self):
            if self.current_idx < len(self.items):
                self.current_idx += 1
                k = self.items[self.current_idx-1]
                return (k,getattr(self,k))
            else:
                raise StopIteration
        def __iter__(self):
           return self

然后称之为可迭代

s=someclass()
for k,v in s:
    print k,"=",v
class someclass:
        x=1
        y=2
        z=3
        def __init__(self):
           self.current_idx = 0
           self.items = ["x","y","z"]
        def next(self):
            if self.current_idx < len(self.items):
                self.current_idx += 1
                k = self.items[self.current_idx-1]
                return (k,getattr(self,k))
            else:
                raise StopIteration
        def __iter__(self):
           return self

then just call it as an iterable

s=someclass()
for k,v in s:
    print k,"=",v

回答 5

正确的答案是您不应该这样做。如果您想要这种类型的东西,要么只使用dict,要么需要将属性显式添加到某个容器中。您可以通过了解装饰器来实现自动化。

尤其是,顺便说一句,示例中的method1同样具有属性。

The correct answer to this is that you shouldn’t. If you want this type of thing either just use a dict, or you’ll need to explicitly add attributes to some container. You can automate that by learning about decorators.

In particular, by the way, method1 in your example is just as good of an attribute.


回答 6

对于python 3.6

class SomeClass:

    def attr_list(self, should_print=False):

        items = self.__dict__.items()
        if should_print:
            [print(f"attribute: {k}    value: {v}") for k, v in items]

        return items

For python 3.6

class SomeClass:

    def attr_list(self, should_print=False):

        items = self.__dict__.items()
        if should_print:
            [print(f"attribute: {k}    value: {v}") for k, v in items]

        return items

回答 7

对于所有的Python狂热分子,我相信Johan Cleeze会赞成您的教条主义;)。我要离开这个答案,继续贬低它,这实际上使我更加知己。留下你的评论!

对于python 3.6

class SomeClass:

    def attr_list1(self, should_print=False):

        for k in self.__dict__.keys():
            v = self.__dict__.__getitem__(k)
            if should_print:
                print(f"attr: {k}    value: {v}")

    def attr_list(self, should_print=False):

        b = [(k, v) for k, v in self.__dict__.items()]
        if should_print:
            [print(f"attr: {a[0]}    value: {a[1]}") for a in b]
        return b

For all the pythonian zealots out there I’m sure Johan Cleeze would approve of your dogmatism ;). I’m leaving this answer keep demeriting it It actually makes me more confidant. Leave a comment you chickens!

For python 3.6

class SomeClass:

    def attr_list1(self, should_print=False):

        for k in self.__dict__.keys():
            v = self.__dict__.__getitem__(k)
            if should_print:
                print(f"attr: {k}    value: {v}")

    def attr_list(self, should_print=False):

        b = [(k, v) for k, v in self.__dict__.items()]
        if should_print:
            [print(f"attr: {a[0]}    value: {a[1]}") for a in b]
        return b

如何访问给定字符串的对象属性,该字符串对应于该属性的名称

问题:如何访问给定字符串的对象属性,该字符串对应于该属性的名称

如何设置/获取t给定的属性的值x

class Test:
   def __init__(self):
       self.attr1 = 1
       self.attr2 = 2

t = Test()
x = "attr1"

How do you set/get the values of attributes of t given by x?

class Test:
   def __init__(self):
       self.attr1 = 1
       self.attr2 = 2

t = Test()
x = "attr1"

回答 0

有称为getattr和的内置函数。setattr

getattr(object, attrname)
setattr(object, attrname, value)

在这种情况下

x = getattr(t, 'attr1')
setattr(t, 'attr1', 21)

There are built-in functions called getattr and setattr

getattr(object, attrname)
setattr(object, attrname, value)

In this case

x = getattr(t, 'attr1')
setattr(t, 'attr1', 21)

回答 1

注意:此答案非常过时。它适用new使用2008不推荐使用的模块的Python 2 。

有内置的python函数setattr和getattr。可以用来设置和获取类的属性。

一个简单的例子:

>>> from new import  classobj

>>> obj = classobj('Test', (object,), {'attr1': int, 'attr2': int}) # Just created a class

>>> setattr(obj, 'attr1', 10)

>>> setattr(obj, 'attr2', 20)

>>> getattr(obj, 'attr1')
10

>>> getattr(obj, 'attr2')
20

Note: This answer is very outdated. It applies to Python 2 using the new module that was deprecated in 2008.

There is python built in functions setattr and getattr. Which can used to set and get the attribute of an class.

A brief example:

>>> from new import  classobj

>>> obj = classobj('Test', (object,), {'attr1': int, 'attr2': int}) # Just created a class

>>> setattr(obj, 'attr1', 10)

>>> setattr(obj, 'attr2', 20)

>>> getattr(obj, 'attr1')
10

>>> getattr(obj, 'attr2')
20

回答 2

如果要将逻辑隐藏在类内部,则可能更喜欢使用通用的getter方法,如下所示:

class Test:
    def __init__(self):
        self.attr1 = 1
        self.attr2 = 2

    def get(self,varname):
        return getattr(self,varname)

t = Test()
x = "attr1"
print ("Attribute value of {0} is {1}".format(x, t.get(x)))

输出:

Attribute value of attr1 is 1

可以更好地隐藏它的另一个方法是使用magic方法__getattribute__,但是我一直遇到一个无限循环,当尝试在该方法中检索属性值时,我无法解决。

另请注意,您也可以使用vars()。在上面的示例中,您可以getattr(self,varname)通过进行交换return vars(self)[varname],但getattr根据之间的区别varssetattr是最好的

If you want to keep the logic hidden inside the class, you may prefer to use a generalized getter method like so:

class Test:
    def __init__(self):
        self.attr1 = 1
        self.attr2 = 2

    def get(self,varname):
        return getattr(self,varname)

t = Test()
x = "attr1"
print ("Attribute value of {0} is {1}".format(x, t.get(x)))

Outputs:

Attribute value of attr1 is 1

Another apporach that could hide it even better would be using the magic method __getattribute__, but I kept getting an endless loop which I was unable to resolve when trying to get retrieve the attribute value inside that method.

Also note that you can alternatively use vars(). In the above example, you could exchange getattr(self,varname) by return vars(self)[varname], but getattrmight be preferable according to the answer to What is the difference between vars and setattr?.


您如何以编程方式设置属性?

问题:您如何以编程方式设置属性?

假设我有一个python对象x和一个字符串s,如何将属性设置为son x?所以:

>>> x = SomeObject()
>>> attr = 'myAttr'
>>> # magic goes here
>>> x.myAttr
'magic'

魔术是什么?顺便说一下,这样做的目的是将对的调用缓存x.__getattr__()

Suppose I have a python object x and a string s, how do I set the attribute s on x? So:

>>> x = SomeObject()
>>> attr = 'myAttr'
>>> # magic goes here
>>> x.myAttr
'magic'

What’s the magic? The goal of this, incidentally, is to cache calls to x.__getattr__().


回答 0

setattr(x, attr, 'magic')

寻求帮助:

>>> help(setattr)
Help on built-in function setattr in module __builtin__:

setattr(...)
    setattr(object, name, value)

    Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
    ``x.y = v''.

编辑:但是,您应该注意(如注释中所指出),您不能对的“纯”实例执行此操作object。但是很可能您有一个简单的对象子类,可以很好地工作。我强烈敦促OP不要创建这样的对象实例。

setattr(x, attr, 'magic')

For help on it:

>>> help(setattr)
Help on built-in function setattr in module __builtin__:

setattr(...)
    setattr(object, name, value)

    Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
    ``x.y = v''.

Edit: However, you should note (as pointed out in a comment) that you can’t do that to a “pure” instance of object. But it is likely you have a simple subclass of object where it will work fine. I would strongly urge the O.P. to never make instances of object like that.


回答 1

通常,我们为此定义类。

class XClass( object ):
   def __init__( self ):
       self.myAttr= None

x= XClass()
x.myAttr= 'magic'
x.myAttr

但是,您可以在一定程度上使用setattrgetattr内置函数来执行此操作。但是,它们不适用于object直接实例。

>>> a= object()
>>> setattr( a, 'hi', 'mom' )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hi'

但是,它们确实适用于各种简单的类。

class YClass( object ):
    pass

y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr

Usually, we define classes for this.

class XClass( object ):
   def __init__( self ):
       self.myAttr= None

x= XClass()
x.myAttr= 'magic'
x.myAttr

However, you can, to an extent, do this with the setattr and getattr built-in functions. However, they don’t work on instances of object directly.

>>> a= object()
>>> setattr( a, 'hi', 'mom' )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hi'

They do, however, work on all kinds of simple classes.

class YClass( object ):
    pass

y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr

回答 2

让x成为一个对象,那么你可以通过两种方式做到这一点

x.attr_name = s 
setattr(x, 'attr_name', s)

let x be an object then you can do it two ways

x.attr_name = s 
setattr(x, 'attr_name', s)

Python函数属性-使用和滥用

问题:Python函数属性-使用和滥用

没有多少人知道此功能,但是Python的函数(和方法)可以具有attribute。看哪:

>>> def foo(x):
...     pass
...     
>>> foo.score = 10
>>> dir(foo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'score']
>>> foo.score
10
>>> foo.score += 1
>>> foo.score
11

Python中此功能的可能用法和滥用是什么?我知道的一个很好的用法是PLY使用docstring将语法规则与方法相关联。但是自定义属性呢?是否有充分的理由使用它们?

Not many are aware of this feature, but Python’s functions (and methods) can have attributes. Behold:

>>> def foo(x):
...     pass
...     
>>> foo.score = 10
>>> dir(foo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'score']
>>> foo.score
10
>>> foo.score += 1
>>> foo.score
11

What are the possible uses and abuses of this feature in Python ? One good use I’m aware of is PLY‘s usage of the docstring to associate a syntax rule with a method. But what about custom attributes ? Are there good reasons to use them ?


回答 0

我通常使用函数属性作为注释的存储。假设我想以C#的方式编写(表示某种方法应该成为Web服务接口的一部分)

class Foo(WebService):
    @webmethod
    def bar(self, arg1, arg2):
         ...

然后我可以定义

def webmethod(func):
    func.is_webmethod = True
    return func

然后,当Web服务调用到达时,我查找该方法,检查基础函数是否具有is_webmethod属性(实际值无关紧要),如果该方法不存在或不打算通过Web调用,则拒绝该服务。

I typically use function attributes as storage for annotations. Suppose I want to write, in the style of C# (indicating that a certain method should be part of the web service interface)

class Foo(WebService):
    @webmethod
    def bar(self, arg1, arg2):
         ...

then I can define

def webmethod(func):
    func.is_webmethod = True
    return func

Then, when a webservice call arrives, I look up the method, check whether the underlying function has the is_webmethod attribute (the actual value is irrelevant), and refuse the service if the method is absent or not meant to be called over the web.


回答 1

我已经将它们用作函数的静态变量。例如,给出以下C代码:

int fn(int i)
{
    static f = 1;
    f += i;
    return f;
}

我可以在Python中类似地实现该功能:

def fn(i):
    fn.f += i
    return fn.f
fn.f = 1

这肯定属于频谱的“滥用”端。

I’ve used them as static variables for a function. For example, given the following C code:

int fn(int i)
{
    static f = 1;
    f += i;
    return f;
}

I can implement the function similarly in Python:

def fn(i):
    fn.f += i
    return fn.f
fn.f = 1

This would definitely fall into the “abuses” end of the spectrum.


回答 2

您可以用JavaScript的方式来做对象…虽然没有任何意义,但是它是可行的;)

>>> def FakeObject():
...   def test():
...     print "foo"
...   FakeObject.test = test
...   return FakeObject
>>> x = FakeObject()
>>> x.test()
foo

You can do objects the JavaScript way… It makes no sense but it works ;)

>>> def FakeObject():
...   def test():
...     print "foo"
...   FakeObject.test = test
...   return FakeObject
>>> x = FakeObject()
>>> x.test()
foo

回答 3

我很少使用它们,但是它们可以很方便:

def log(msg):
   log.logfile.write(msg)

现在,我可以log在整个模块中使用,只需设置即可重定向输出log.logfile。有很多其他方法可以实现这一点,但是这种方法轻巧而简单。虽然我第一次这样做时闻起来很可笑,但我开始相信它闻起来比具有全局logfile变量更好。

I use them sparingly, but they can be pretty convenient:

def log(msg):
   log.logfile.write(msg)

Now I can use log throughout my module, and redirect output simply by setting log.logfile. There are lots and lots of other ways to accomplish that, but this one’s lightweight and dirt simple. And while it smelled funny the first time I did it, I’ve come to believe that it smells better than having a global logfile variable.


回答 4

函数属性可用于编写将代码和关联数据包装在一起的轻量级闭包:

#!/usr/bin/env python

SW_DELTA = 0
SW_MARK  = 1
SW_BASE  = 2

def stopwatch():
   import time

   def _sw( action = SW_DELTA ):

      if action == SW_DELTA:
         return time.time() - _sw._time

      elif action == SW_MARK:
         _sw._time = time.time()
         return _sw._time

      elif action == SW_BASE:
         return _sw._time

      else:
         raise NotImplementedError

   _sw._time = time.time() # time of creation

   return _sw

# test code
sw=stopwatch()
sw2=stopwatch()
import os
os.system("sleep 1")
print sw() # defaults to "SW_DELTA"
sw( SW_MARK )
os.system("sleep 2")
print sw()
print sw2()

1.00934004784

2.00644397736

3.01593494415

Function attributes can be used to write light-weight closures that wrap code and associated data together:

#!/usr/bin/env python

SW_DELTA = 0
SW_MARK  = 1
SW_BASE  = 2

def stopwatch():
   import time

   def _sw( action = SW_DELTA ):

      if action == SW_DELTA:
         return time.time() - _sw._time

      elif action == SW_MARK:
         _sw._time = time.time()
         return _sw._time

      elif action == SW_BASE:
         return _sw._time

      else:
         raise NotImplementedError

   _sw._time = time.time() # time of creation

   return _sw

# test code
sw=stopwatch()
sw2=stopwatch()
import os
os.system("sleep 1")
print sw() # defaults to "SW_DELTA"
sw( SW_MARK )
os.system("sleep 2")
print sw()
print sw2()

1.00934004784

2.00644397736

3.01593494415


回答 5

我创建了这个辅助装饰器来轻松设置函数属性:

def with_attrs(**func_attrs):
    """Set attributes in the decorated function, at definition time.
    Only accepts keyword arguments.
    E.g.:
        @with_attrs(counter=0, something='boing')
        def count_it():
            count_it.counter += 1
        print count_it.counter
        print count_it.something
        # Out:
        # >>> 0
        # >>> 'boing'
    """
    def attr_decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            return fn(*args, **kwargs)

        for attr, value in func_attrs.iteritems():
            setattr(wrapper, attr, value)

        return wrapper

    return attr_decorator

用例是创建工厂的集合,并查询它们可以在功能元级别创建的数据类型。
例如(非常愚蠢):

@with_attrs(datatype=list)
def factory1():
    return [1, 2, 3]

@with_attrs(datatype=SomeClass)
def factory2():
    return SomeClass()

factories = [factory1, factory2]

def create(datatype):
    for f in factories:
        if f.datatype == datatype:
            return f()
    return None

I’ve created this helper decorator to easily set function attributes:

def with_attrs(**func_attrs):
    """Set attributes in the decorated function, at definition time.
    Only accepts keyword arguments.
    E.g.:
        @with_attrs(counter=0, something='boing')
        def count_it():
            count_it.counter += 1
        print count_it.counter
        print count_it.something
        # Out:
        # >>> 0
        # >>> 'boing'
    """
    def attr_decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            return fn(*args, **kwargs)

        for attr, value in func_attrs.iteritems():
            setattr(wrapper, attr, value)

        return wrapper

    return attr_decorator

A use case is to create a collection of factories and query the data type they can create at a function meta level.
For example (very dumb one):

@with_attrs(datatype=list)
def factory1():
    return [1, 2, 3]

@with_attrs(datatype=SomeClass)
def factory2():
    return SomeClass()

factories = [factory1, factory2]

def create(datatype):
    for f in factories:
        if f.datatype == datatype:
            return f()
    return None

回答 6

有时,我使用函数的属性来缓存已计算的值。您也可以使用通用装饰器来概括此方法。注意此类功能的并发问题和副作用!

Sometimes I use an attribute of a function for caching already computed values. You can also have a generic decorator that generalizes this approach. Be aware of concurrency issues and side effects of such functions!


回答 7

我一直以为,这是唯一可能的原因,因此在逻辑上可以放置文档字符串或其他类似的东西。我知道如果我将它用于任何生产代码,都会使大多数阅读它的人感到困惑。

I was always of the assumption that the only reason this was possible was so there was a logical place to put a doc-string or other such stuff. I know if I used it for any production code it’d confuse most who read it.


如何创建对象并为其添加属性?

问题:如何创建对象并为其添加属性?

我想在Python中创建一个动态对象(在另一个对象内部),然后向其添加属性。

我试过了:

obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')

但这没用。

有任何想法吗?

编辑:

我正在从for循环遍历值列表的循环中设置属性,例如

params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()

for p in params:
   obj.a.p # where p comes from for loop variable

在上面的例子中,我会得到obj.a.attr1obj.a.attr2obj.a.attr3

我使用该setattr函数是因为我不知道如何obj.a.NAMEfor循环中进行操作。

如何根据上例中的值设置属性p

I want to create a dynamic object (inside another object) in Python and then add attributes to it.

I tried:

obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')

but this didn’t work.

Any ideas?

edit:

I am setting the attributes from a for loop which loops through a list of values, e.g.

params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()

for p in params:
   obj.a.p # where p comes from for loop variable

In the above example I would get obj.a.attr1, obj.a.attr2, obj.a.attr3.

I used the setattr function because I didn’t know how to do obj.a.NAME from a for loop.

How would I set the attribute based on the value of p in the example above?


回答 0

您可以使用我的古老的Bunch配方,但是如果您不想创建“绑定类”,那么Python中已经存在一个非常简单的类-所有函数都可以具有任意属性(包括lambda函数)。因此,以下工作:

obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')

与古老的Bunch食谱相比,清晰度是否还可以,这是一个样式决定,我当然会留给您。

You could use my ancient Bunch recipe, but if you don’t want to make a “bunch class”, a very simple one already exists in Python — all functions can have arbitrary attributes (including lambda functions). So, the following works:

obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')

Whether the loss of clarity compared to the venerable Bunch recipe is OK, is a style decision I will of course leave up to you.


回答 1

内置object实例可以实例化,但是不能设置任何属性。(为此,我希望可以。)它没有一个__dict__用于保存属性的属性。

我通常只是这样做:

class Object(object):
    pass

a = Object()
a.somefield = somevalue

如果可以的话,Object根据我要输入的数据类型,给该类一个更有意义的名称。

某些人做不同的事情,他们使用的子类dict允许属性访问获得关键。(d.key代替d['key']

编辑:对于您的问题的补充,使用setattr就可以了。您只是不能setattrobject()实例上使用。

params = ['attr1', 'attr2', 'attr3']
for p in params:
    setattr(obj.a, p, value)

The built-in object can be instantiated but can’t have any attributes set on it. (I wish it could, for this exact purpose.) It doesn’t have a __dict__ to hold the attributes.

I generally just do this:

class Object(object):
    pass

a = Object()
a.somefield = somevalue

When I can, I give the Object class a more meaningful name, depending on what kind of data I’m putting in it.

Some people do a different thing, where they use a sub-class of dict that allows attribute access to get at the keys. (d.key instead of d['key'])

Edit: For the addition to your question, using setattr is fine. You just can’t use setattr on object() instances.

params = ['attr1', 'attr2', 'attr3']
for p in params:
    setattr(obj.a, p, value)

回答 2

types.SimpleNamespacePython 3.3+中有一个

obj = someobject
obj.a = SimpleNamespace()
for p in params:
    setattr(obj.a, p, value)
# obj.a.attr1

collections.namedtupletyping.NamedTuple可用于不可变的对象。PEP 557-数据类 建议了一种可变的替代方法。

要获得更丰富的功能,可以尝试使用attrspackage。请参阅用法示例

There is types.SimpleNamespace class in Python 3.3+:

obj = someobject
obj.a = SimpleNamespace()
for p in params:
    setattr(obj.a, p, value)
# obj.a.attr1

collections.namedtuple, typing.NamedTuple could be used for immutable objects. PEP 557 — Data Classes suggests a mutable alternative.

For a richer functionality, you could try attrs package. See an example usage.


回答 3

有几种方法可以实现此目标。基本上,您需要一个可扩展的对象。

obj.a = type('Test', (object,), {})  
obj.a.b = 'fun'  

obj.b = lambda:None

class Test:
  pass
obj.c = Test()

There are a few ways to reach this goal. Basically you need an object which is extendable.

obj.a = type('Test', (object,), {})  
obj.a.b = 'fun'  

obj.b = lambda:None

class Test:
  pass
obj.c = Test()

回答 4

mock模块基本上是为此目的而设计的。

import mock
obj = mock.Mock()
obj.a = 5

The mock module is basically made for that.

import mock
obj = mock.Mock()
obj.a = 5

回答 5

现在,您可以执行操作(不确定答案是否与罪恶相同):

MyObject = type('MyObject', (object,), {})
obj = MyObject()
obj.value = 42

Now you can do (not sure if it’s the same answer as evilpie):

MyObject = type('MyObject', (object,), {})
obj = MyObject()
obj.value = 42

回答 6

请尝试以下代码:

$ python
>>> class Container(object):
...     pass 
...
>>> x = Container()
>>> x.a = 10
>>> x.b = 20
>>> x.banana = 100
>>> x.a, x.b, x.banana
(10, 20, 100)
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__',     '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana']

Try the code below:

$ python
>>> class Container(object):
...     pass 
...
>>> x = Container()
>>> x.a = 10
>>> x.b = 20
>>> x.banana = 100
>>> x.a, x.b, x.banana
(10, 20, 100)
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__',     '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana']

回答 7

您也可以直接使用类对象。它创建一个命名空间:

class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')

You can also use a class object directly; it creates a namespace:

class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')

回答 8

正如文档所说

object__dict__,所以你不能指定任意属性的实例object类。

您可以只使用伪类实例。

as docs say:

Note: object does not have a __dict__, so you can’t assign arbitrary attributes to an instance of the object class.

You could just use dummy-class instance.


回答 9

这些解决方案在测试期间非常有帮助。基于其他人的答案,我在Python 2.7.9中执行此操作(没有静态方法,我得到TypeError(未绑定方法…):

In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4

These solutions are very helpful during testing. Building on everyone else’s answers I do this in Python 2.7.9 (without staticmethod I get a TypeError (unbound method…):

In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4

回答 10

您正在使用哪些对象?只是尝试了一个示例类,它运行良好:

class MyClass:
  i = 123456
  def f(self):
    return "hello world"

b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test

我得到123了答案。

我看到此失败的唯一情况是,如果您正在尝试setattr对内置对象进行操作。

更新:从注释中可以看出是重复的:为什么不能在python中向对象添加属性?

Which objects are you using? Just tried that with a sample class and it worked fine:

class MyClass:
  i = 123456
  def f(self):
    return "hello world"

b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test

And I got 123 as the answer.

The only situation where I see this failing is if you’re trying a setattr on a builtin object.

Update: From the comment this is a repetition of: Why can’t you add attributes to object in python?


回答 11

到今天晚了,这是我的一分钱,它的对象恰好在应用程序中保留了一些有用的路径,但是您可以将其适应于任何您希望通过getattr和点表示法访问信息的命令(这是我认为这个问题的真正含义):

import os

def x_path(path_name):
    return getattr(x_path, path_name)

x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
    setattr(x_path, name, os.path.join(x_path.root, name))

这很酷,因为现在:

In [1]: x_path.projects
Out[1]: '/home/x/projects'

In [2]: x_path('caches')
Out[2]: '/home/x/caches'

因此,它像上面的答案一样使用函数对象,但使用函数来获取值(您仍然可以使用,(getattr, x_path, 'repository')而不是x_path('repository')愿意使用)。

Coming to this late in the day but here is my pennyworth with an object that just happens to hold some useful paths in an app but you can adapt it for anything where you want a sorta dict of information that you can access with getattr and dot notation (which is what I think this question is really about):

import os

def x_path(path_name):
    return getattr(x_path, path_name)

x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
    setattr(x_path, name, os.path.join(x_path.root, name))

This is cool because now:

In [1]: x_path.projects
Out[1]: '/home/x/projects'

In [2]: x_path('caches')
Out[2]: '/home/x/caches'

So this uses the function object like the above answers but uses the function to get the values (you can still use (getattr, x_path, 'repository') rather than x_path('repository') if you prefer).


回答 12

如果在创建嵌套对象之前可以确定所有属性和值并将它们聚合在一起,那么我们可以创建一个新类,该类在创建时采用字典参数。

# python 2.7

class NestedObject():
    def __init__(self, initial_attrs):
        for key in initial_attrs:
            setattr(self, key, initial_attrs[key])

obj = someobject
attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' }
obj.a = NestedObject(attributes)
>>> obj.a.attr1
'val1'
>>> obj.a.attr2
'val2'
>>> obj.a.attr3
'val3'

我们还可以允许关键字参数。看到这篇文章

class NestedObject(object):
    def __init__(self, *initial_attrs, **kwargs):
        for dictionary in initial_attrs:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])


obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3')

If we can determine and aggregate all the attributes and values together before creating the nested object, then we could create a new class that takes a dictionary argument on creation.

# python 2.7

class NestedObject():
    def __init__(self, initial_attrs):
        for key in initial_attrs:
            setattr(self, key, initial_attrs[key])

obj = someobject
attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' }
obj.a = NestedObject(attributes)
>>> obj.a.attr1
'val1'
>>> obj.a.attr2
'val2'
>>> obj.a.attr3
'val3'

We can also allow keyword arguments. See this post.

class NestedObject(object):
    def __init__(self, *initial_attrs, **kwargs):
        for dictionary in initial_attrs:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])


obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3')

回答 13

di = {}
for x in range(20):
    name = '_id%s' % x
    di[name] = type(name, (object), {})
    setattr(di[name], "attr", "value")
di = {}
for x in range(20):
    name = '_id%s' % x
    di[name] = type(name, (object), {})
    setattr(di[name], "attr", "value")

回答 14

我看到的其他方式是这样的:

import maya.cmds

def getData(objets=None, attrs=None):
    di = {}
    for obj in objets:
        name = str(obj)
        di[name]=[]
        for at in attrs:
            di[name].append(cmds.getAttr(name+'.'+at)[0])
    return di

acns=cmds.ls('L_vest_*_',type='aimConstraint')
attrs=['offset','aimVector','upVector','worldUpVector']

getData(acns,attrs)

Other way i see, this way:

import maya.cmds

def getData(objets=None, attrs=None):
    di = {}
    for obj in objets:
        name = str(obj)
        di[name]=[]
        for at in attrs:
            di[name].append(cmds.getAttr(name+'.'+at)[0])
    return di

acns=cmds.ls('L_vest_*_',type='aimConstraint')
attrs=['offset','aimVector','upVector','worldUpVector']

getData(acns,attrs)