-2

This is what I have:

Site = namedtuple('Site', 'number x y')
Sites = namedtuple('Sites', 'p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14')

my_sites = Sites(Site('p1', 607, 184),
                 Site('p2', 698, 254),
                 Site('p3', 821, 309),
                 Site('p4', 569, 237),
                 Site('p5', 647, 302),
                 Site('p6', 727, 374),
                 Site('p7', 437, 289),
                 Site('p8', 548, 358),
                 Site('p9', 650, 416),
                 Site('p10', 352, 333),
                 Site('p11', 451, 432),
                 Site('p12', 222, 435),
                 Site('p13', 338, 507),
                 Site('p14', 431, 579))

And this is what I want to do:

cc = 1;

for x in build:

    x = my_sites.p[cc].x
    y = my_sites.p[cc].y

    cc = cc + 1

build is just a random list.

This, instead is the error I get:

AttributeError: 'Sites' object has no attribute 'p'

Is there any way to solve this?

martineau
  • 119,623
  • 25
  • 170
  • 301
TrustMe
  • 9
  • 1
  • 5
  • 1
    use `getattr(..)`. – Willem Van Onsem Oct 18 '18 at 17:50
  • I don't know if this would solve your problem, but change your `for` loop's iterating variable to something other than `x` if you're going to use it for some other process inside the loop. – Irfanuddin Oct 18 '18 at 17:51
  • 1
    Why *would you iterate a namedtuple object*, iterating a tuple absolutely *does not make sense* – Antti Haapala -- Слава Україні Oct 18 '18 at 17:52
  • 1
    Have you considered using a list instead? – Antti Haapala -- Слава Україні Oct 18 '18 at 17:53
  • TrustMe: The error is because Instances of the `tuple` subclass `Sites` you defined **don't** have a `p` attribute, they have attributes named `p1`, `p2`, `p3`, etc – martineau Oct 18 '18 at 18:07
  • @martineau I would guess that the comment is in relation to immutability of tuples so if you're having to search for something, you're not using the correct structure where a particular field should be expected at a particular index. But I'd be interested in Antti's clarification if it comes :) – roganjosh Oct 18 '18 at 18:11
  • 2
    @Antti HaapalaL Iterating a `namedtuple` instance makes as much sense as iterating any other sequence—such as a `tuple` or `list`—and might occur in some contexts (e.g. such as how the contents would be accessed inside a function that requires only that the argument passed to it is something iterable, such as `sum()`). That said, the situation shown in this particular question doesn't appear to be such a case. – martineau Oct 18 '18 at 18:14
  • 1
    @roganjosh: The OP doesn't appear to be trying to mutate the `namedtuple`s as far as I can tell—so I don't think your guess is correct. Regardless, it will be interesting to see what, if anything, Antti has to say in response. – martineau Oct 18 '18 at 18:23

1 Answers1

1

Question: How to iterate on a namedtuple object?

As pointed out: use getattr(..). – Willem Van Onsem
As pointed out: Sites ... don't have a p ..., they have p1, p2, p3, etc – martineau

You have to use it like this:

from collections import namedtuple

Site = namedtuple('Site', 'number x y')
Sites = namedtuple('Sites', 'p1 p2 p3')

my_sites = Sites(Site(1, 607, 184), Site(2, 698, 254), Site(3, 821, 309))

for x in [1,2,3]:
    attr = "p{}".format(x)
    site = getattr(my_sites, attr)
    print("{}:{}".format(attr, site))

for attr in ['p1', 'p2', 'p3']:
    print("{}:{}".format(attr, getattr(my_sites, attr)))

print("p2:{}".format(my_sites.p2))

Output:

p1:Site(number=1, x=607, y=184)
p2:Site(number=2, x=698, y=254)
p3:Site(number=3, x=821, y=309)
Site(number=2, x=698, y=254)

Tested with Python: 3.4.2

stovfl
  • 14,998
  • 7
  • 24
  • 51