0

This follows on from a previous query of mine Static initializer in Python I am trying to find an object from one of it's properties as I would with a static constructor in java:

public class TestBuilder {
private String uid;
private String name;
private double speed;
private static ArrayList<TestBuilder> types = new ArrayList<TestBuilder>();
public static final TestBuilder SLEEPY;
public static final TestBuilder SPEEDY;

static {
    SLEEPY = new TestBuilder("1", "slow test", 500.00);
    SPEEDY = new TestBuilder("2", "fast test", 2000.00);
}

private TestBuilder(String uid, String name, double speed){
    this.uid = uid;
    this.name = name;
    this.speed = speed;
    types.add(this);
}

public static TestBuilder getBuilderFromName(String s){
    for (int i = 0; i < types.size(); i++){
        if (((TestBuilder) types.get(i)).name.equals(s)){
            return (TestBuilder) types.get(i);
        }
    }
    return null;
}

In python I have tried:

class TestBuilder:
    uid = str()
    name = str()
    speed = float()
    types = []

    def __init__(self, uid, name, speed):
        self.uid = uid
        self.name = name
        self.speed = speed
        self.types.append(self)

    @classmethod
    def lookupType(cls, name):
        for item in cls.types:
            if item.name == name:
                return cls

TestBuilder.SLEEPY = TestBuilder("1","slow test", 500.0)
TestBuilder.SPEEDY = TestBuilder("2","fast test", 2000.0)

Then in a test module:

class Tester(unittest.TestCase):
    def test_builder(self):
        dummy = TestBuilder
        ref = dummy.SPEEDY
        objfound = dummy.lookupType("slow test")
        logger.debug("--test_builder() name: "+objfound.name)

While the correct object is found in the lookupType method the resultant classfound name property is empty when accessed in the test. How can I access the correct TestBuilder object given one of it's properties?

1 Answer 1

3

You are returning the class, not the instance you found:

@classmethod
def lookupType(cls, name):
    for item in cls.types:
        if item.name == name:
            return cls
            #      ^^^

Return the item instead:

return item

Instead of using a list, register your classes using a dictionary so you can simply look them up by name:

class TestBuilder:
    types = {}

    def __init__(self, uid, name, speed):
        self.uid = uid
        self.name = name
        self.speed = speed
        self.types[name] = self

    @classmethod
    def lookupType(cls, name):
        return cls.types.get(name)

Note that your uid = str() and speed = float() lines simply create class attributes set to an empty string and 0.0 respectively. Those lines do not declare a type and Python won't stop your code from assigning different objects to those attributes at the instance level.

Sign up to request clarification or add additional context in comments.

8 Comments

Much appreciated. NB I changed the types declaration to types = {}
@DonSmythe: oops, that's a typo on my part, corrected.
I would suggest using a variable name other than types, as it is the name of a module within the standard Python library.
@Yani: that hardly matters here; it is a class attribute here, so it is namespaced.
@MartijnPieters - True, but it's good practice in my opinion.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.