1

I have a class:

Each member of the class has a value that corresponds to two coordinates (x, y)

class Building:

    h_armory = (284, 384)
    h_dependance = (176, 320)
    h_villa = (244, 188)
    h_library = (410, 168)
    h_storage = (504, 152)
    h_garage = (624, 159)
    h_workshop = (674, 211)
    h_caveau = (562, 132)
    h_entry = (693, 354)
    h_wall = (401, 442)
    h_guard = (612, 393)

Now, in a function i have a for cycle.

How can i access to the class members values using a syntax like this:

def myFunction():

    cc = 0

    for x in (Building):

          coord = x[cc]

          cc = cc + 1
TrustMe
  • 9
  • 1
  • 5
  • 1
    1. What's the desired iteration order? Is sorted ok? Will all attributes start with `h_`? 2. Are you sure that all your attributes should be defined at the class level, are they constant for every building? 2. What problem are you trying to solve with the iteration? This could be an XY problem. – timgeb Oct 09 '18 at 15:31
  • The iteration order i't the same of the class, i din't put all the members and not everyone starts with h_. And yes, all the attributes are costant. I want just to put the value in a variable so i can use the coordinates. – TrustMe Oct 09 '18 at 15:34
  • 1
    If you find yourself iterating on attributes for common operations, then it is likely that you should use a mapping instead of standard class attributes. Hard to say more without the context... – Serge Ballesta Oct 09 '18 at 15:35
  • @MaorRefaeli this has the problem of also producing attributes like `__weakref__` because we're operating at the class level. – timgeb Oct 09 '18 at 15:36
  • are the values coordinates, by any chance? – timgeb Oct 09 '18 at 15:39
  • @timgeb Yes, they are. – TrustMe Oct 09 '18 at 15:41
  • @timgeb I updated the code of the for cycle. I don't know if it's the most correct way to do it, but this is what i want to do. – TrustMe Oct 09 '18 at 15:51
  • 1
    Possible duplicate of https://stackoverflow.com/questions/28685828/python-2-7-how-to-get-the-list-of-static-variables-in-a-class – Maor Refaeli Oct 09 '18 at 15:55
  • @MaorRefaeli I tried but it gives me an error: `classobj is not iterable` – TrustMe Oct 09 '18 at 15:59

1 Answers1

0

You have a design problem here.

First of all, the class does not remember the order of attributes assigned to it. Second, in order to make the class (not an instance) iterable we would have to dive into metaprogramming, which is certainly overkill for what you are trying to do. Third, your class just holds a bunch of data without any methods, which often is a waste of a class. You might as well use a dictionary or an OrderedDict from the collections module.

But there is a better way. Cue named tuples, which solve your problem much more elegantly and are iterable. The following demonstration uses only three attributes for brevity.

>>> from collections import namedtuple
>>>
>>> Coordinate = namedtuple('Coordinate', 'location x y')
>>> Building = namedtuple('Building', 'h_armory h_dependence h_villa')
>>>
>>> my_building = Building(Coordinate('h_armory', 284, 384),
...                        Coordinate('h_dependance', 176, 320),
...                        Coordinate('h_villa', 244, 188))
>>>
>>> for location, x, y in my_building:
...      print(location, x, y)
... 
h_armory 284 384
h_dependance 176 320
h_villa 244 188

(I used your names, but as far as I can tell the name City or Village would make more sense than the name Building, because the latter seems to be holding the coordinates of a bunch of different buildings.)

timgeb
  • 76,762
  • 20
  • 123
  • 145
  • Seems this can work well for me. I have just one question, does it work with the same principle as a class or do I have to declare everything in the function? – TrustMe Oct 09 '18 at 16:07
  • @TrustMe I don't understand your question. Maybe you should play around with `my_building` in the interpreter. You can access attributes similarly as in your original class. For example `print(my_building.h_villa.y)` -> `188`. – timgeb Oct 09 '18 at 16:09