increment the name of the variable, ex: prdt1, prdt2, prdt3 ...etc - python

I didn't try anything because I don't even know where to start...
the program would associate every item of the list to the variables like (name)1, (name)2, (name)3, and so on to the number of items the list has.
prdt = ["WD40", "001", "oleo de carro, 1L", "liquidos", "seccao 1", 5, 30]
prdt1 ="WD40"
prdt2 ="001"
prdt3 ="oleo de carro, 1L"
prdt4 ="liquidos"
a program that creates a variable incremented by 1 in a for a loop.

Basically with python version above 3.8 you can use eval and walrus operator in order to achieve this behaviour. You will get variables with names corresponding to your list items
for idx, item in enumerate(prdt):
eval(f"({item}{idx}:={item})")
If you look at this weird syntax in eval it's walrus operator := combined with a parenthesis and all that in a f-string. Very unreadable and ugly solution imho, but eval only allows for expressions, NOT compound statements (so you cannot use the regular assignment with = ).
And you have int values in your list, which will cause the above code to fail, since var name in python cannot be an int... 5=5 is not a legal code, neither are values with spaces...Overall sorry to say, but this question does not make too much sense to be honest.
But in general it sounds like a terrible idea to be honest (whatever is your usecase). If you need to associate specific names with values you should use dict probably.

Related

Python : Adding data to list

I am learning lists and trying to create a list and add data to it.
mylist=[]
mylist[0]="hello"
This generates Error.
Why cant we add members to lists like this, like we do with arrays in javascript.
Since these are also dynamic and we can add as many members and of any data type to it.
In javascript this works:
var ar=[];
ar[0]=333;
Why this dosent work in Python and we only use append() to add to list.
mylist[0] = 'hello' is syntactic sugar for mylist.__setitem__(0, 'hello').
As per the docs for object.__setitem__(self, key, value):
The same exceptions should be raised for improper key values as for
the __getitem__() method.
The docs for __getitem__ states specifically what leads to IndexError:
if value outside the set of indexes for the sequence (after any
special interpretation of negative values), IndexError should be
raised.
As to the purpose behind this design decision, one can write several chapters to explain why list has been designed in this way. You should familiarise yourself with Python list indexing and slicing before making judgements on its utility.
Lists in Python are fundamentally different to arrays in languages like C. You do not create a list of a fixed size and assign elements to indexes in it. Instead you either create an empty list and append elements to it, or use a list-comprehension to generate a list from a type of expression.
In your case, you want to add to the end, so you must use the .append method:
mylist.append('hello')
#["hello"]
And an example of a list comprehension:
squares = [x**2 for x in range(10)]
#[1,4,9,16,25,36,49,64,81,100]

Python list comprehension with dummy names identical to iterator name: ill-advised?

Say I make a list comprehension that looks something like this:
i = range(5)
a = [f(i) for i in i]
for some function f. Will using a dummy name identical to the iterator ever yield unexpected results? Sometimes I have variable names that are individual letters, and to me it is more readable to stick with the same letter rather than assigning a new one, like [f(x) for x in x] instead of [f(i) for i in x] (for instance, if the letter of the iterator x is meaningful, I will wonder what the heck i is).
TL;DR: It is safe, technically, but it's a poor choice stylistically.
In a list comprehension, before binding the free variable of the for-loop to any object, Python will use a GET_ITER opcode on the iterable to get an iterator. This is done just once at the beginning of the loop.
Therefore in the body of the "loop" of the list comprehension (which actually creates a scope in Python 3), you may rebind the name which originally pointed to the iterable without any consequence. The iteration deals with a reference to the iterator directly, and whether or not it has a name in scope is irrelevant. The same should hold true in Python 2, though the scoping implementation details are different: the name of the collection will be lost after the comprehension, as the loop variable name will remain bound to the final element of iteration.
There is no advantage to writing the code in this way, and it is less readable than just avoiding the name collision. So, you should prefer to name the collection so that it more obvious that it is a collection:
[f(x) for x in xs]
While you can get away with using duplicate variable names due to the way Python executes list comprehensions - even nested list comprehensions -
don't do this. It may seem more readable in your opinion, but for most people, it would be very confusing.
This leads to a much more important point, however. Why use a name like i, j, or x at all? Using single letter variable names cause confusion and are ambiguous. Instead, use a variable name which clearly conveys your intent.
Or, if you don't have an need at all for the values in the iterable your iterating through(eg. You simple want to repeat a block of code a certain number of times), use a "throw-away" variable, _, to convey to the reader of your code that the value is not important and should be ignored.
But don't use non-descriptive, duplicate, single letter variable names. That will only serve to confuse future readers of your code, make your intent unclear, and create code hard to maintain and debug.
Because in the end, would you rather maintain code like this
[str(x) for x in x]
or this?
[str(user_id) for user_id in user_ids]

Call variable from two concatenated strings Python

I have some code that generates two strings - digit_ and 'x', where x is an integer. My gut feeling is that this is a stupid question, but I can't find an answer online. I have variables called digit_1, digit_2 ... etc up to digit_9. How can I call the correct one of these without using a really long if/elif function? Is there a way of calling a variable from a concatenation of it's name?
Sam
The cleanest way is to put the variables into a list or a dictionary, and then access them by index or by name.
No, there isn't a good way to "create" variable names and access them.
However, you can just use a list, and index into it instead.

How clever is the python interpreter?

Probably a stupid question, but I am wondering in general, and if anyone knows, how much foresight the Python interpreter has, specifically in the field of regular expressions and text parsing.
Suppose my code at some point looks like this:
mylist = ['a', 'b', 'c', ... ]
if 'g' in list: print(mylist.index('g'))
is there any safer way to do this with a while loop or similar. I mean, will the index be looked up with a second parsing from the beginning or are the two g's (in the above line) the same thing in Python's mind?
It'll do the lookup both times. If it's worth it (for, say, a very big list), use try:
try:
print(mylist.index('g'))
except ValueError:
pass
The result of the containment check is not cached, and so the index will need to be discovered anew. And the dynamic nature of Python makes implicit caching of such a thing unreliable since the __contains__() method may mutate the object (although it would be a violation of several programming principles to do so).
Your code will result in two lookups, first to determine if 'g' is in the list and second to find the index. Python won't try to consolidate them into a single lookup. If you're worried about efficiency you can use a dictionary instead of a list which will make both lookups O(1) instead of O(n).
You can easily make a dict to look up. Something like this:
mydict = {k:v for v,k in enumerate(mylist)}
The overhead of creating the dict won't be worthwhile unless you are doing a few such lookups on the same list
Try is better option to find the index of element in list.
try:
print(mylist.index('g'))
except ValueError:
print "value not in list"
pass
yeah it will be looked up twice, the python interpreter doesn't cache instructions, though I've being wondering if its possible (for certain things), if this is an issue, then you can use sets or dicts both of which have constant look up time.
Either way it seems you are LBYL, in python we tend to EAFP so its quite common to wrap such things in try ... except blocks

Difference between two "contains" operations for python lists

I'm fairly new to python and have found that I need to query a list about whether it contains a certain item.
The majority of the postings I have seen on various websites (including this similar stackoverflow question) have all suggested something along the lines of
for i in list
if i == thingIAmLookingFor
return True
However, I have also found from one lone forum that
if thingIAmLookingFor in list
# do work
works.
I am wondering if the if thing in list method is shorthand for the for i in list method, or if it is implemented differently.
I would also like to which, if either, is more preferred.
In your simple example it is of course better to use in.
However... in the question you link to, in doesn't work (at least not directly) because the OP does not want to find an object that is equal to something, but an object whose attribute n is equal to something.
One answer does mention using in on a list comprehension, though I'm not sure why a generator expression wasn't used instead:
if 5 in (data.n for data in myList):
print "Found it"
But this is hardly much of an improvement over the other approaches, such as this one using any:
if any(data.n == 5 for data in myList):
print "Found it"
the "if x in thing:" format is strongly preferred, not just because it takes less code, but it also works on other data types and is (to me) easier to read.
I'm not sure how it's implemented, but I'd expect it to be quite a lot more efficient on datatypes that are stored in a more searchable form. eg. sets or dictionary keys.
The if thing in somelist is the preferred and fastest way.
Under-the-hood that use of the in-operator translates to somelist.__contains__(thing) whose implementation is equivalent to: any((x is thing or x == thing) for x in somelist).
Note the condition tests identity and then equality.
for i in list
if i == thingIAmLookingFor
return True
The above is a terrible way to test whether an item exists in a collection. It returns True from the function, so if you need the test as part of some code you'd need to move this into a separate utility function, or add thingWasFound = False before the loop and set it to True in the if statement (and then break), either of which is several lines of boilerplate for what could be a simple expression.
Plus, if you just use thingIAmLookingFor in list, this might execute more efficiently by doing fewer Python level operations (it'll need to do the same operations, but maybe in C, as list is a builtin type). But even more importantly, if list is actually bound to some other collection like a set or a dictionary thingIAmLookingFor in list will use the hash lookup mechanism such types support and be much more efficient, while using a for loop will force Python to go through every item in turn.
Obligatory post-script: list is a terrible name for a variable that contains a list as it shadows the list builtin, which can confuse you or anyone who reads your code. You're much better off naming it something that tells you something about what it means.

Categories

Resources