0

I'm new to python and maybe this doesn't sound logic but how can I make this to work:

p1=(20,50)
p2=(70,80)
p3=(100,140)
listP=[]
#listP=[p1,p2,p3] #manually it works
for i in range(3):
    listP.append('p'+str(i))

The result should be a list of point, instead of (p1,p2 etc) Thanks a lot in advance!

JeanFr
  • 19
  • 1
  • 2

3 Answers3

1

In your example, p1, p2, p3 are identifiers, but in your for-loop, you add the names of these identifiers as strings to your list. Consequently, you obtain a list of strings, not a list of dereferenced values for identifiers that matched these strings. This behavior is intended and desired.

Identifiers are kind of named handles you use in your code to access the values they reference. In general, no programming language automatically converts strings that may match some local identifiers into actual references, as this is unintended behavior in most cases. Think of scope and security.

Usually, you should not try to convert strings into identifiers. In python, you can do so using getattr. However, I'll not outline this here, because, again, you should not do so.

The better approach for your case is to directly instantiate your points in a list or dict structure:

# List:
plist = [(20, 50), (70, 80), (100, 140)]

# Dict:
pdict = {
    'p1': (20, 50),
    'p2': (70, 80),
    'p3': (100, 140)
}

In these cases, you can access your points like so:

# For list case:
for i in range(3):
    print(plist[i])

# For dict case:
for i in range(3):
    print(pdict['p{:d}'.format(i)])
jbndlr
  • 4,965
  • 2
  • 21
  • 31
  • Agreed that using dictionaries seems like the right approach. But sometimes it's also helpful to know how to dynamically access variable names.. – Wingston Sharon Dec 13 '16 at 08:11
  • Creating variable names as strings and dereferencing them dynamically is bad coding on almost all levels. Indeed it's nice to know, but usually it indicates a major design flaw if you have to do it. What about debugging, refactoring, inspection (to name but few)? – jbndlr Dec 13 '16 at 08:13
  • Very much agreed, a design/algorithm change in the program is required. – Wingston Sharon Dec 13 '16 at 08:20
  • Thanks a lot for all reponces, very helpfull! – JeanFr Dec 13 '16 at 11:09
1

If You want to access variables using their names as strings, You can use locals() or vars() (thanks @Wingston Sharon for this) to do this:

# Using locals()
for i in range(3):
    listP.append(locals()['p' + str(i)])

# Using vars()
for i in range(3):
    listP.append(vars()['p' + str(i)])
Fejs
  • 2,734
  • 3
  • 21
  • 40
  • 1
    This is a solution Y for problem X (see the [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)) and a very hacky solution at that. – TigerhawkT3 Dec 13 '16 at 10:31
1

you can use vars()

for i in range(1,4):
    listP.append(vars()['p'+str(i)])
Wingston Sharon
  • 1,030
  • 2
  • 11
  • 21