Different meanings of brackets in Python - python

I am curious, what do the 3 different brackets mean in Python programming? Not sure if I'm correct about this, but please correct me if I'm wrong:
[] - Normally used for dictionaries, list items
() - Used to identify params
{} - I have no idea what this does...
Or if these brackets can be used for other purposes, any advice is welcomed! Thanks!

Square brackets: []
Lists and indexing/lookup/slicing
Lists: [], [1, 2, 3], [i**2 for i in range(5)]
Indexing: 'abc'[0] → 'a'
Lookup: {0: 10}[0] → 10
Slicing: 'abc'[:2] → 'ab'
Parentheses: () (AKA "round brackets")
Tuples, order of operations, generator expressions, function calls and other syntax.
Tuples: (), (1, 2, 3)
Although tuples can be created without parentheses: t = 1, 2 → (1, 2)
Order of operations: (n-1)**2
Generator expressions: (i**2 for i in range(5))
Function or method calls: print(), int(), range(5), '1 2'.split(' ')
with a generator expression: sum(i**2 for i in range(5))
Curly braces: {}
Dictionaries and sets, as well as in string formatting
Dicts: {}, {0: 10}, {i: i**2 for i in range(5)}
Sets: {0}, {i**2 for i in range(5)}
Except the empty set: set()
In string formatting to indicate replacement fields:
F-strings: f'{foobar}'
Format strings: '{}'.format(foobar)
Regular expressions
All of these brackets are also used in regex. Basically, [] are used for character classes, () for grouping, and {} for repetition. For details, see The Regular Expressions FAQ.
Angle brackets: <>
Used when representing certain objects like functions, classes, and class instances if the class doesn't override __repr__(), for example:
>>> print
<built-in function print>
>>> zip
<class 'zip'>
>>> zip()
<zip object at 0x7f95df5a7340>
(Note that these aren't proper Unicode angle brackets, like ⟨⟩, but repurposed less-than and greater-than signs.)

In addition to Maltysen's answer and for future readers: you can define the () and [] operators in a class, by defining the methods:
__call__(self[, args...]) for ()
__getitem__(self, key) for []
An example is numpy.mgrid[...]. In this way you can define it on your custom-made objects for any purpose you like.

() parentheses are used for order of operations, or order of evaluation, and are referred to as tuples.
[] brackets are used for lists. List contents can be changed, unlike tuple content.
{} are used to define a dictionary in a "list" called a literal.

Tuple is immutable(order inside it can't be changed once created),and are enclosed in parenthesis,separated by ("," or ','). Tuple is used to store multiple items in a single variable.
Example:
thistupple("apple","banana","mango")
print(thistupple)
Output:
('apple', 'banana', 'cherry')

Related

my_set.copy().add( something ) why return None [duplicate]

What am I doing wrong here?
a = set().add(1)
print a # Prints `None`
I'm trying to add the number 1 to the empty set.
It is a convention in Python that methods that mutate sequences return None.
Consider:
>>> a_list = [3, 2, 1]
>>> print a_list.sort()
None
>>> a_list
[1, 2, 3]
>>> a_dict = {}
>>> print a_dict.__setitem__('a', 1)
None
>>> a_dict
{'a': 1}
>>> a_set = set()
>>> print a_set.add(1)
None
>>> a_set
set([1])
Some may consider this convention "a horrible misdesign in Python", but the Design and History FAQ gives the reasoning behind this design decision (with respect to lists):
Why doesn’t list.sort() return the sorted list?
In situations where performance matters, making a copy of the list
just to sort it would be wasteful. Therefore, list.sort() sorts the
list in place. In order to remind you of that fact, it does not return
the sorted list. This way, you won’t be fooled into accidentally
overwriting a list when you need a sorted copy but also need to keep
the unsorted version around.
In Python 2.4 a new built-in function – sorted() – has been added.
This function creates a new list from a provided iterable, sorts it
and returns it.
Your particular problems with this feature come from a misunderstanding of good ways to create a set rather than a language misdesign. As Lattyware points out, in Python versions 2.7 and later you can use a set literal a = {1} or do a = set([1]) as per Sven Marnach's answer.
Parenthetically, I like Ruby's convention of placing an exclamation point after methods that mutate objects, but I find Python's approach acceptable.
The add() method adds an element to the set, but it does not return the set again -- it returns None.
a = set()
a.add(1)
or better
a = set([1])
would work.
Because add() is modifing your set in place returning None:
>>> empty = set()
>>> print(empty.add(1))
None
>>> empty
set([1])
Another way to do it that is relatively simple would be:
a = set()
a = set() | {1}
this creates a union between your set a and a set with 1 as the element
print(a) yields {1} then because a would now have all elements of both a and {1}
You should do this:
a = set()
a.add(1)
print a
Notice that you're assigning to a the result of adding 1, and the add operation, as defined in Python, returns None - and that's what is getting assigned to a in your code.
Alternatively, you can do this for initializing a set:
a = set([1, 2, 3])
The add method updates the set, but returns None.
a = set()
a.add(1)
print a
You are assigning the value returned by set().add(1) to a. This value is None, as add() does not return any value, it instead acts in-place on the list.
What you wanted to do was this:
a = set()
a.add(1)
print(a)
Of course, this example is trivial, but Python does support set literals, so if you really wanted to do this, it's better to do:
a = {1}
print(a)
The curly brackets denote a set (although be warned, {} denotes an empty dict, not an empty set due to the fact that curly brackets are used for both dicts and sets (dicts are separated by the use of the colon to separate keys and values.)
Alternatively to a = set() | {1} consider "in-place" operator:
a = set()
a |= {1}

Define two members of a list simultaneously using a function that returns a tuple - Python

This is what I wish I could do:
def f: return 1, 2
list = {
"a","b": f()
}
Is there any way to set two elements of a list simultaneously with a single function call?
>>> dict(zip(('a', 'b'), f()))
{'a': 1, 'b': 2}
Set your attributes after creating the dict:
dct = {}
dct['a'], dct['b'] = f()
Multiple assignment works only when assigning, not in a dict literal notation.
It appears, from your psuedo-code that you want a dictionary, not a list, but it's worth a note that if PEP-448 comes to fruition (currently slated for 3.4), unpacking into a list will be easy with a syntax familiar to python users - * (the unpacking operator):
>>> def f(): return 1, 2
>>> a_list = [*f]
>>> a_list
[1, 2]

How to identify a generator vs list comprehension

I have this:
>>> sum( i*i for i in xrange(5))
My question is, in this case am I passing a list comprehension or a generator object to sum ? How do I tell that? Is there a general rule around this?
Also remember sum by itself needs a pair of parentheses to surround its arguments. I'd think that the parentheses above are for sum and not for creating a generator object. Wouldn't you agree?
You are passing in a generator expression.
A list comprehension is specified with square brackets ([...]). A list comprehension builds a list object first, so it uses syntax closely related to the list literal syntax:
list_literal = [1, 2, 3]
list_comprehension = [i for i in range(4) if i > 0]
A generator expression, on the other hand, creates an iterator object. Only when iterating over that object is the contained loop executed and are items produced. The generator expression does not retain those items; there is no list object being built.
A generator expression always uses (...) round parethesis, but when used as the only argument to a call, the parenthesis can be omitted; the following two expressions are equivalent:
sum((i*i for i in xrange(5))) # with parenthesis
sum(i*i for i in xrange(5)) # without parenthesis around the generator
Quoting from the generator expression documentation:
The parentheses can be omitted on calls with only one argument. See section Calls for the detail.
List comprehensions are enclosed in []:
>>> [i*i for i in xrange(5)] # list comprehension
[0, 1, 4, 9, 16]
>>> (i*i for i in xrange(5)) # generator
<generator object <genexpr> at 0x2cee40>
You are passing a generator.
That is a generator:
>>> (i*i for i in xrange(5))
<generator object <genexpr> at 0x01A27A08>
>>>
List comprehensions are enclosed in [].
You might also be asking, "does this syntax truly cause sum to consume a generator one item at a time, or does it secretly create a list of every item in the generator first"? One way to check this is to try it on a very large range and watch memory usage:
sum(i for i in xrange(int(1e8)))
Memory usage for this case is constant, where as range(int(1e8)) creates the full list and consumes several hundred MB of RAM.
You can test that the parentheses are optional:
def print_it(obj):
print obj
print_it(i for i in xrange(5))
# prints <generator object <genexpr> at 0x03853C60>
I tried this:
#!/usr/bin/env python
class myclass:
def __init__(self,arg):
self.p = arg
print type(self.p)
print self.p
if __name__ == '__main__':
c = myclass(i*i for i in xrange(5))
And this prints:
$ ./genexprorlistcomp.py
<type 'generator'>
<generator object <genexpr> at 0x7f5344c7cf00>
Which is consistent with what Martin and mdscruggs explained in their post.
You are passing a generator object, list comprehension is surrounded by [].

Difference accessing element(s) of tuple and list

Why is there this difference accessing the element(s) of t when making it a tuple?
>>> t = [('ID','int')]
>>> for r in t:
print r
('ID', 'int')
t = (('ID','int'))
>>> for r in t:
print r
ID
int
I'd expect this to be exactly the same as the first example! Whereas populating the tuple with more than one element the behavior changes.
>>> t = (('ID','int'),('DEF','str'))
>>> for r in t:
print r
('ID', 'int')
('DEF', 'str')
>>> t = [('ID','int'),('DEF','str')]
>>> for r in t:
print r
('ID', 'int')
('DEF', 'str')
Can somebody give a short explanation? I'm running python 2.7
(('a', 'b')) is the same as ('a', 'b').
You actually want (('a', 'b'),)
This is documented here:
5.13. Expression lists
expression_list ::= expression ( "," expression )* [","]
An expression list containing at least one comma yields a tuple. The length of the tuple is the number of expressions in the list. The expressions are evaluated from left to right.
The trailing comma is required only to create a single tuple (a.k.a. a singleton); it is optional in all other cases. A single expression without a trailing comma doesn’t create a tuple, but rather yields the value of that expression. (To create an empty tuple, use an empty pair of parentheses: ().)
Remember, that without this restriction, should the expression (3) * (4) be the multiplication of two numbers, or two tuples? Most users would expect that to be the multiplication of numbers.
t = [('ID','int')]
is a tuple in a list.
t = (('ID','int'))
is a tuple with brackets around it.
t = ('ID','int'),
is a tuple in a tuple.
The , makes the tuple! The brackets around a tuple are only needed to avoid ambiguity.

Add number to set

What am I doing wrong here?
a = set().add(1)
print a # Prints `None`
I'm trying to add the number 1 to the empty set.
It is a convention in Python that methods that mutate sequences return None.
Consider:
>>> a_list = [3, 2, 1]
>>> print a_list.sort()
None
>>> a_list
[1, 2, 3]
>>> a_dict = {}
>>> print a_dict.__setitem__('a', 1)
None
>>> a_dict
{'a': 1}
>>> a_set = set()
>>> print a_set.add(1)
None
>>> a_set
set([1])
Some may consider this convention "a horrible misdesign in Python", but the Design and History FAQ gives the reasoning behind this design decision (with respect to lists):
Why doesn’t list.sort() return the sorted list?
In situations where performance matters, making a copy of the list
just to sort it would be wasteful. Therefore, list.sort() sorts the
list in place. In order to remind you of that fact, it does not return
the sorted list. This way, you won’t be fooled into accidentally
overwriting a list when you need a sorted copy but also need to keep
the unsorted version around.
In Python 2.4 a new built-in function – sorted() – has been added.
This function creates a new list from a provided iterable, sorts it
and returns it.
Your particular problems with this feature come from a misunderstanding of good ways to create a set rather than a language misdesign. As Lattyware points out, in Python versions 2.7 and later you can use a set literal a = {1} or do a = set([1]) as per Sven Marnach's answer.
Parenthetically, I like Ruby's convention of placing an exclamation point after methods that mutate objects, but I find Python's approach acceptable.
The add() method adds an element to the set, but it does not return the set again -- it returns None.
a = set()
a.add(1)
or better
a = set([1])
would work.
Because add() is modifing your set in place returning None:
>>> empty = set()
>>> print(empty.add(1))
None
>>> empty
set([1])
Another way to do it that is relatively simple would be:
a = set()
a = set() | {1}
this creates a union between your set a and a set with 1 as the element
print(a) yields {1} then because a would now have all elements of both a and {1}
You should do this:
a = set()
a.add(1)
print a
Notice that you're assigning to a the result of adding 1, and the add operation, as defined in Python, returns None - and that's what is getting assigned to a in your code.
Alternatively, you can do this for initializing a set:
a = set([1, 2, 3])
The add method updates the set, but returns None.
a = set()
a.add(1)
print a
You are assigning the value returned by set().add(1) to a. This value is None, as add() does not return any value, it instead acts in-place on the list.
What you wanted to do was this:
a = set()
a.add(1)
print(a)
Of course, this example is trivial, but Python does support set literals, so if you really wanted to do this, it's better to do:
a = {1}
print(a)
The curly brackets denote a set (although be warned, {} denotes an empty dict, not an empty set due to the fact that curly brackets are used for both dicts and sets (dicts are separated by the use of the colon to separate keys and values.)
Alternatively to a = set() | {1} consider "in-place" operator:
a = set()
a |= {1}

Categories