How can I create a new instance of a list or dictionary every time a method is called? The closest thing I can compare what I would like to do is the new keyword in java or C#
These functions are already defined, there are constructors of built in types - dictionary and list:
x = dict()
y = list()
which is an equivalent of Java's
Map x = new TreeMap(); // or other dictionary implementation
List y = new ArrayList(); // or other list implementation
Assuming you have a default list L and you want to make sure you're working with a list equal to L and not mutating L itself, you could initialize a local variable to list(L). Is that what you mean?
Dictionary example:
def create_dict():
return {}
List example:
def create_list():
return []
Usage:
a = create_dict() #for a new empty dictionary
b = create_list() # for new empty list
This all works but is not really that useful as it stands.
The most common way (by far) is:
y= [] # new empty list
x= {} # new empty dictionary
Why so short? Because the language encourages the usage of high-level data structures like these.
In Python, constructors are invoked with the name of the class (like Java), but with no need for new or any other keyword. As mentioned in another answer(s), this makes the following syntax also valid:
x= list()
y= dict()
However, you will rarely find them in practice.
List literals (like [1,2,3,4]) create new lists and pre-populate them. Dictionary literals (like {'Red':'Rojo','Yellow':'Amarillo','Green':'Verde'}) create new dictionaries and pre-populate them too.
Set literals (like {'Morning','Afternoon','Evening','Night'}) are also valid. However, empty sets require to be created as set(). The syntax {} is reserved to create empty dictionaries as they are more common.
Related
This might be simple, but I'm stuck. I have globals() that creates dictionaries based on zipping lists (that will differ in sizes, thus differ in the number of the dictionaries that get created). The new dictionaries that get created look like the below:
dict0 = {foo:bar}
dict1 = {more_foo:more_bar}
How do I call these new dictionaries in a for loop?
I want my script to do the below:
for i in (dict0, dict1):
The only issue is that the number of dictx (dictionaries) will differ based on the inputs from the script.
As nicely put in comments, in your case, you should append the dictionaries to a list:
list_iterator = list()
# create dict 1.
list_iterator.append(dict1)
# create dict 2.
list_iterator.append(dict2)
# and so on. If your dict create algorithm is repetetive, you can add the append command to the end.
I figured it out...
for i in range(len(someList)):
dicts = locals()['dict' + str(i)]
I'm trying to add items to an array in python.
I run
array = {}
Then, I try to add something to this array by doing:
array.append(valueToBeInserted)
There doesn't seem to be a .append method for this. How do I add items to an array?
{} represents an empty dictionary, not an array/list. For lists or arrays, you need [].
To initialize an empty list do this:
my_list = []
or
my_list = list()
To add elements to the list, use append
my_list.append(12)
To extend the list to include the elements from another list use extend
my_list.extend([1,2,3,4])
my_list
--> [12,1,2,3,4]
To remove an element from a list use remove
my_list.remove(2)
Dictionaries represent a collection of key/value pairs also known as an associative array or a map.
To initialize an empty dictionary use {} or dict()
Dictionaries have keys and values
my_dict = {'key':'value', 'another_key' : 0}
To extend a dictionary with the contents of another dictionary you may use the update method
my_dict.update({'third_key' : 1})
To remove a value from a dictionary
del my_dict['key']
If you do it this way:
array = {}
you are making a dictionary, not an array.
If you need an array (which is called a list in python ) you declare it like this:
array = []
Then you can add items like this:
array.append('a')
Arrays (called list in python) use the [] notation. {} is for dict (also called hash tables, associated arrays, etc in other languages) so you won't have 'append' for a dict.
If you actually want an array (list), use:
array = []
array.append(valueToBeInserted)
Just for sake of completion, you can also do this:
array = []
array += [valueToBeInserted]
If it's a list of strings, this will also work:
array += 'string'
In some languages like JAVA you define an array using curly braces as following but in python it has a different meaning:
Java:
int[] myIntArray = {1,2,3};
String[] myStringArray = {"a","b","c"};
However, in Python, curly braces are used to define dictionaries, which needs a key:value assignment as {'a':1, 'b':2}
To actually define an array (which is actually called list in python) you can do:
Python:
mylist = [1,2,3]
or other examples like:
mylist = list()
mylist.append(1)
mylist.append(2)
mylist.append(3)
print(mylist)
>>> [1,2,3]
You can also do:
array = numpy.append(array, value)
Note that the numpy.append() method returns a new object, so if you want to modify your initial array, you have to write: array = ...
Isn't it a good idea to learn how to create an array in the most performant way?
It's really simple to create and insert an values into an array:
my_array = ["B","C","D","E","F"]
But, now we have two ways to insert one more value into this array:
Slow mode:
my_array.insert(0,"A") - moves all values to the right when entering an "A" in the zero position:
"A" --> "B","C","D","E","F"
Fast mode:
my_array.append("A")
Adds the value "A" to the last position of the array, without touching the other positions:
"B","C","D","E","F", "A"
If you need to display the sorted data, do so later when necessary. Use the way that is most useful to you, but it is interesting to understand the performance of each method.
I believe you are all wrong. you need to do:
array = array[] in order to define it, and then:
array.append ["hello"] to add to it.
I have a function which returns strings. What I would like to do is get these strings and save it into a list. How can I do this?
for i in objects:
string = getstring(i)
x = 0
list[x] = string
x = x+1
You should first declare the list:
L = []
then, in the for loop, you can append items to it:
for i in objects:
string = getstring(i)
L.append(string)
It is better to use a list comprehension in this case,
my_list = [getstring(obj) for obj in objects]
Instead of creating a list and storing string in it, we are creating a list of strings, based on the objects in objects. You can do the same with map function as well
my_list = map(getstring, objects)
This takes each and every item in objects and applies getstring function to them. All the results are gathered in a list. If you are using Python 3.x, then you might want to do
my_list = list(map(getstring, objects))
Since using map is not preferred, whenever possible go with List Comprehension. Quoting from the BDFL's blog,
Curiously, the map, filter, and reduce functions that originally motivated the introduction of lambda and other functional features have to a large extent been superseded by list comprehensions and generator expressions.
I have tried to define a function to create a two-tiered dictionary, so it should produce the format
dict = {tier1:{tier2:value}}.
The code is:
def two_tier_dict_init(tier1,tier2,value):
dict_name = {}
for t1 in tier1:
dict_name[t1] = {}
for t2 in tier2:
dict_name[t1][t2] = value
return dict_name
So the following example...
tier1 = ["foo","bar"]
tier2 = ["x","y"]
value = []
foobar_dict = two_tier_dict_init(tier1,tier2,value)
on the face of it produces what I want:
foobar_dict = {'foo':{'x': [],'y':[]},
'bar':{'x': [],'y':[]}} }
However, when appending any value like
foobar_dict["foo"]["x"].append("thing")
All values get appended so the result is:
foobar_dict = {'foo':{'x': ["thing"],'y':["thing"]},
'bar':{'x': ["thing"],'y':["thing"]}}
At first I assumed that due to the way my definition builds the dictionary that all values are pointing to the same space in memory, but I could not figure out why this should be the case. I then discovered that if I change the value from an empty list to an integer, when I do the following,
foobar_dict["foo"]["x"] +=1
only the desired value is changed.
I must therefore conclude that it is something to do with the list.append method, but I can not figure it out. What is the explanation?
N.B. I require this function for building large dictionaries of dictionaries where each tier has hundreds of elements. I have also used the same method to build a three-tiered version with the same issue occurring.
You only passed in one list object, and your second-tier dictionary only stored references to that one object.
If you need to store distinct lists, you need to create a new list for each entry. You could use a factory function for that:
def two_tier_dict_init(tier1, tier2, value_factory):
dict_name = {}
for t1 in tier1:
dict_name[t1] = {}
for t2 in tier2:
dict_name[t1][t2] = value_factory()
return dict_name
Then use:
two_tier_dict_init(tier1, tier2, list)
to have it create empty lists. You can use any callable for the value factory here, including a lambda if you want to store an immutable object like a string or an integer:
two_tier_dict_init(tier1, tier2, lambda: "I am shared but immutable")
You could use a dict comprehension to simplify your function:
def two_tier_dict_init(tier1, tier2, value_factory):
return {t1: {t2: value_factory() for t2 in tier2} for t1 in tier1}
It happens because you are filling all second-tier dicts with the same list that you passed as value, and all entries are pointing to the same list object.
One solution is to copy the list at each attribution:
dict_name[t1][t2] = value[:]
This only works if you are sure that value is always a list.
Another, more generic solution, that works with any object, including nested lists and dictionaries, is deep copying:
dict_name[t1][t2] = copy.deepcopy(value)
If you fill the dicts with an immutable object like a number or string, internally all entries would refer to the same object as well, but the undesirable effect would not happen because numbers and strings are immutable.
All the values refer to the same list object. When you call append() on that list object, all of the dictionary values appear to change at the same time.
To create a copy of the list change
dict_name[t1][t2] = value
to
dict_name[t1][t2] = value[:]
or to
dict_name[t1][t2] = copy.deepcopy(value)
The former will make a shallow (i.e. one-level) copy, and the latter will do a deep copy.
The reason this appears to work with ints is because they are immutable, and augmented assignments (+= and friends) do a name rebind just like ordinary assignment statements (it just might be back to the same object). When you do this:
foobar_dict["foo"]["x"] +=1
you end up replacing the old int object with a different one. ints have no capability to change value in-place, so the addition builds (or, possibly finds, since CPython interns certain ints) a different int with the new value.
So even if foobar_dict["foo"]["x"] and foobar_dict["foo"]["y"] started out with the same int (and they did), adding to one of them makes them now contain different ints.
You can see this difference if you try it out with simpler variables:
>>> a = b = 1
>>> a is b
True
>>> a += 1
>>> a
2
>>> b
1
On the other hand, list is mutable, and calling append doesn't do any rebinding. So, as you suspected, if foobar_dict["foo"]["x"] and foobar_dict["foo"]["y"] are the same list (and they are - check this with is), and you append to it, they are still the same list.
I'm a looking to initialize an array/list of objects that are not empty -- the class constructor generates data. In C++ and Java I would do something like this:
Object lst = new Object[100];
I've dug around, but is there a Pythonic way to get this done?
This doesn't work like I thought it would (I get 100 references to the same object):
lst = [Object()]*100
But this seems to work in the way I want:
lst = [Object() for i in range(100)]
List comprehension seems (intellectually) like "a lot" of work for something that's so simple in Java.
There isn't a way to implicitly call an Object() constructor for each element of an array like there is in C++ (recall that in Java, each element of a new array is initialised to null for reference types).
I would say that your list comprehension method is the most Pythonic:
lst = [Object() for i in range(100)]
If you don't want to step on the lexical variable i, then a convention in Python is to use _ for a dummy variable whose value doesn't matter:
lst = [Object() for _ in range(100)]
For an equivalent of the similar construct in Java, you can of course use *:
lst = [None] * 100
You should note that Python's equvalent for Java code
(creating array of 100 null references to Object):
Object arr = new Object[100];
or C++ code:
Object **arr = new Object*[100];
is:
arr = [None]*100
not:
arr = [Object() for _ in range(100)]
The second would be the same as Java's:
Object arr = new Object[100];
for (int i = 0; i < arr.lenght; i++) {
arr[i] = new Object();
}
In fact Python's capabilities to initialize complex data structures are far better then Java's.
Note:
C++ code:
Object *arr = new Object[100];
would have to do as much work as Python's list comprehension:
allocate continuous memory for 100 Objects
call Object::Object() for each of this Objects
And the result would be a completely different data structure.
I think the list comprehension is the simplest way, but, if you don't like it, it's obviously not the only way to obtain what you desire -- calling a given callable 100 times with no arguments to form the 100 items of a new list. For example, itertools can obviously do it:
>>> import itertools as it
>>> lst = list(it.starmap(Object, it.repeat((), 100)))
or, if you're really a traditionalist, map and apply:
>>> lst = map(apply, 100*[Object], 100*[()])
Note that this is essentially the same (tiny, both conceptually and actually;-) amount of work it would take if, instead of needing to be called without arguments, Object needed to be called with one argument -- or, say, if Object was in fact a function rather than a type.
From your surprise that it might take "as much as a list comprehension" to perform this task, you appear to think that every language should special-case the need to perform "calls to a type, without arguments" over other kinds of calls to over callables, but I fail to see what's so crucial and special about this very specific case, to warrant treating it differently from all others; and, as a consequence, I'm pretty happy, personally, that Python doesn't single this one case out for peculiar and weird treatment, but handles just as regularly and easily as any other similar use case!-)
lst = [Object() for i in range(100)]
Since an array is it's own first class object in python I think this is the only way to get what you're looking for. * does something crazy.