简体   繁体   中英

Python: Find Instance of a class by value

i created much instances of a class. Then I want to find one instance by its name. But I get the error message TypeError: get() missing 1 required positional argument: 'value' .

class Test(object):
    def __init__(self, value):
        self.value = value

    def get(self, value):
        if self.value == value:
            return self
        else:
            return None

test_obj = Test('foobar')

print(test_obj.value)

instance = Test.get('foobar')

if instance:
    print(instance.value)

The get method belongs to the instance, not the class. A class does not know its instances (you could do some dirty tricks to let the class know, but don't). What you need is a list of instances.

One way you could do it

  1. override the equality operator
  2. create a list of the instances

So, something like

class Test:
    def __eq__(self, value):
    return self.value == value

test_list = [Test(5), Test(2), Test(3)]

position = test_list.index(2)

Re-reading your question again, I think all of us have missed the point so far. You wanted to check all instances of the class Test to see if an instance has the value 'foobar' (in this case, test_obj . Referencing this answer , you can modify your code like so:

class Test(object):
    # class attribute to keep track of class instances
    instances = []
    def __init__(self, value):
        self.value = value
        Test.instances.append(self)

    # class method to access the get method without any instance
    @classmethod
    def get(cls, value):
        return [inst for inst in cls.instances if inst.value == value]

You can then create multiple tests:

test1 = Test(1)
test2 = Test(2)
test3 = Test(3)

instance = Test.get(3)
# [<__main__.Test object at 0x03F29CD0>]

instance[0].value
# 3

It makes sense for me to return a list of instances instead of one single instance. If you however is only interested in the first match, you can modify the return statement accordingly.


Original answer:

instance = Test.get('foobar') is the problem. You're referencing Test by its class, not its instance. So naturally the instance method .get(self, value) is looking for the first argument self for the instance.

Usually if you already have an instance (eg Test().get('foobar') ) then the instance is passed into the instance method as self by default.

You could still call the instance method, but you just need to explicitly pass the instance in:

Test.get(test, 'foobar')

The "get" method of your class is not a class method therefore you have to call it on the instance:

test.get("foobar")

However if you modify the method to a classmethod than it won't be able to access the instance attributes only the class atributes will be visible. For a quick solution I think you should store all of the instances in a datastructure (for example in a list) and you can create a function which will loop through the instances and returns the correct one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM