0

I'm quite new in Python, but googling around did not match any answer for it .

I created a module, containing 10 GUI buttons classes. To use a button I write in code ButtonLib.TypeA(**kwargs), ButtonLib.TypeB(**kwargs) and so on. kwargs is same for all buttons.

Buttons ( amount and type ) are selected by user (stored in button_type_vector) and not known in advance.

I wish to know if there is a way writing code more efficiently rather than:

for x in button_type_vector:
    if x == 'TypeA':
        ButtonLib.TypeA(**kwargs)
    elif x== 'TypeB' :
        ButtonLib.TypeB(**kwargs)

and so on.

by efficiently I mean something like:

for x in button_type_vector:
    ButtonLib.x(**kwargs)

thnks

guyd
  • 693
  • 2
  • 14
  • 32
  • I don't quite understand your code. Iterating over `range` produces _integers_, but you're comparing `x` to _strings_. Shouldn't you be iterating directly over `button_type_vector`? – Christian Dean Oct 19 '17 at 16:55
  • @ChristianDean -sorry. fixing it – guyd Oct 19 '17 at 16:56
  • 1
    It is not Python, but rather OOP field. You should define BaseButton class with abstract .TypeX method, and use this class as parent for every Button Type, assigning specific function to .TypeX in the constructor. Then you just call YourButton.TypeX(**kwargs) – GSazheniuk Oct 19 '17 at 16:58
  • @ChristianDean. Why did you delete your answer? – Mad Physicist Oct 19 '17 at 17:03
  • 1
    @MadPhysicist Eh well, after I had finished posting my answer, I realized that this was probably a pretty common duplicate question. So I figured I should vote to close instead of answering it. – Christian Dean Oct 19 '17 at 17:06
  • @MadPhysicist I don't think it would've done much harm if I had keep my answer posted, but I deiced since nobody had responded to it yet, I should do the "right" thing to do. – Christian Dean Oct 19 '17 at 17:19
  • @ChristianDean the link given give a solution in case I seek to get or set attr value, in my case I wish to create a class obj from a module , containing 10 different classes – guyd Oct 19 '17 at 18:04
  • @Guy.D. The piece of information you are missing seems to be that a module is an object that has attributes just like any other. You can access them by name using `getattr` just like the answer to the dupe suggests. – Mad Physicist Oct 19 '17 at 23:15
  • @ChristianDean. I think you should reinstate your answer, if only to save OP the additional confusion. While it will pay in the long run to have them think it out on their own, your answer is a great demo for the fact that modules are just another type of Python object. There is nothing exceptionally magical about them. – Mad Physicist Oct 19 '17 at 23:17
  • @MadPhysicist Alright, I see your points. It's up again ;-) – Christian Dean Oct 20 '17 at 01:19

2 Answers2

2

You can use the getattr built-in function to access attributes of an object using strings:

Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

for x in button_type_vector:
    getattr(ButtonLib, x)(**kwargs)

As mentioned by @MadPyhisist, modules are not some kind of magical object, and thus can be used with like any normal object could be getattr.

Christian Dean
  • 22,138
  • 7
  • 54
  • 87
1

You could define a dictionary (preferably inside your module):

buttons = {
    "TypeA": TypeA,
    "TypeB": TypeB,
    …
}

and then call the entry:

ButtonLib.buttons[x](**kwargs)

If your button classes have a function returning their name, you could also define the dictionary like this:

buttons = {
    button_type.name: button_type
    for button_type in [TypeA, TypeB, …]
}

More advanced: Python stores the name of a class in .__name__. Even more advanced: You could get the elements of the module with getattr(ButtonLib, name). But this might impair readability.

YSelf
  • 2,646
  • 1
  • 14
  • 19