Defining a dict with a tuple singleton key - python

To define a singleton in python use singleton = ('singleton'),
A Python dictionary can use a tuple as a key, as in
[('one', 'two'): 5]
But is it possible to do
[('singleton'),: 5]
Somehow?

Yes, you can do this — but not with ('Singleton'). You've got to use ('Singleton',).
The reason for this is that Python will interpret single parentheses around a single item as merely the item itself. Adding a comma enforces the tuple interpretation.
>>> d = {}
>>> d[('Thing')] = "one"
>>> d.keys()
['Thing']
>>> d[('Thing',)] = "another"
>>> d
{'Thing': 'one', ('Thing',): 'another'}

Signify to python that 'singleton' is a tuple to make it work:
>>> a = {}
>>> a[('singleton',)] = 5
>>> a
{('singleton',): 5}

Related

What the different between {} and set() in python [duplicate]

In PyCharm, when I write:
return set([(sy + ady, sx + adx)])
it says "Function call can be replaced with set literal" so it replaces it with:
return {(sy + ady, sx + adx)}
Why is that? A set() in Python is not the same as a dictionary {}?
And if it wants to optimize this, why is this more effective?
Python sets and dictionaries can both be constructed using curly braces:
my_dict = {'a': 1, 'b': 2}
my_set = {1, 2, 3}
The interpreter (and human readers) can distinguish between them based on their contents. However it isn't possible to distinguish between an empty set and an empty dict, so this case you need to use set() for empty sets to disambiguate.
A very simple test suggests that the literal construction is faster (python3.5):
>>> timeit.timeit('a = set([1, 2, 3])')
0.5449375328607857
>>> timeit.timeit('a = {1, 2, 3}')
0.20525191631168127
This question covers some issues of performance of literal constructions over builtin functions, albeit for lists and dicts. The summary seems to be that literal constructions require less work from the interpreter.
It is an alternative syntax for set()
>>> a = {1, 2}
>>> b = set()
>>> b.add(1)
>>> b.add(2)
>>> b
set([1, 2])
>>> a
set([1, 2])
>>> a == b
True
>>> type(a) == type(b)
True
dict syntax is different. It consists of key-value pairs. For example:
my_obj = {1:None, 2:None}
Another example how set and {} are not interchangeable (as jonrsharpe mentioned):
In: f = 'FH'
In: set(f)
Out: {'F', 'H'}
In: {f}
Out: {'FH'}
set([iterable]) is the constructor to create a set from the optional iterable iterable. And {} is to create set / dict object literals. So what is created depends on how you use it.
In [414]: x = {}
In [415]: type(x)
Out[415]: dict
In [416]: x = {1}
In [417]: type(x)
Out[417]: set
In [418]: x = {1: "hello"}
In [419]: type(x)
Out[419]: dict

Get first and second values in dictionary in CPython 3.6

Now that dictionaries are ordered in python 3.6, it must be the case that there is a way to get the first and second values of a dictionary in only two lines. Right now, I have to use 7 lines to accomplish this:
for key, value in class_sent.items():
i += 1
if i == 1:
first_sent = value
elif i == 2:
second_sent = value
I also tried:
first_sent = next(iter(class_sent))
second_sent = next(iter(class_sent))
But in that case the second_sent is equal to the first_sent. If anyone knows how to obtain the first and second values in a dictionary in as few lines as possible I would seriously appreciate it.
Right now Python only guarantees that the order of **kwargs and class attributes are preserved.
Considering that the implementation of Python you're using guarantees this behaviour you could do.
Using itertools.islice.
>>> from itertools import islice
>>> dct = {'a': 1, 'b': 2, 'c': 3}
>>> first, second = islice(dct.values(), 2)
>>> first, second
(1, 2)
Using iter().
>>> it = iter(dct.values())
>>> first, second = next(it), next(it)
>>> first, second
(1, 2)
Using extended iterable unpacking(will result in unnecessary unpacking of other values as well):
>>> first, second, *_ = dct.values()
>>> first, second
(1, 2)
This could work:
first_sent, second_sent = list(class_sent.values())[:2]

Why is there no insert() method for strings in Python?

Lists already have an insert() method that works with indexes:
>>> someList = [1, 2, 4, 5]
>>> someList
[1, 2, 4, 5]
>>> someList.insert(2, 3)
>>> someList
[1, 2, 3, 4, 5]
If strings also have indexes, why not an insert() method for them too? Example below:
>>> someString = 'foobar'
>>> someString.insert(3, 'SPAM')
>>> someString
'fooSPAMbar'
Short answer: Because strings are immutable.
Every type in Python is either mutable (like a list, a dictionary, or a normal object) , or immutable (like tuples, strings, ints, ...).
That's why you can append, pop, and insert in and from lists, but not tuples.
When you do something like this:
a = "this"
a = a + "that"
a seems to have "changed" to "thisthat", but actually, the name a just points to a new string. You can observe that effect if you hand something to a function and try to modify it in the function: Mutable types will also change outside (although you should usually avoid these side-effects), while immutables won't:
a = 3
b = [3]
def change_a(something):
something = 4
def change_b(something):
something[0] = 4
change_a(a)
change_b(b)
print(a,b) # prints "3 4"
If you need to mutate strings, you might want to look into StringIO for Python 2, or io.StringIO for Python 3, respectively:
import io
def insert(s,where,what):
whatlen=len(what)
s.seek(0)
cur=len(s.read())
if cur < where:
raise IndexError("Can't insert at position {}: Index out of bounds"
.format(where))
s.seek(where)
r=s.read()
s.seek(where+whatlen)
s.write(r)
s.seek(where)
s.write(what)
s = io.StringIO("This is a test")
insert(s,5,"hello")
s.seek(0)
print(s.read()) #prints "This hellois a test"
Because strings are immutable. You can't change the contents of a string. You'd have to make a new string.
Because strings are decidedly immutable. As are tuples.
Traditional strings are immutable. You can actually use the deprecated MutableString to do this:
string = UserString.MutableString('foobar') # then insert, call string.insert(3, 'SPAM')
Hence List are a mutable we can make changes in a list. But Strings ar ean immutable one, we can append charaters in a string. But we cannot change the index position values in a string.

Why can't a tuple be a key for a dictionary in python?

Why can't I do the below thing :
a = (1,2,3)
dict[a] = 'hi'
TypeError: 'type' object does not support item assignment
It can be. The problem is you're trying to access an item in the dict type itself.
>>> a = (1,2,3)
>>> d = {}
>>> d[a] = "hi"
>>> d
{(1, 2, 3): 'hi'}
As #mgilson put it in a comment: "Tuples can be hashed as long as all of their elements can be hashed."
(Note that you should never name your dictionaries dict, or lists list, etc. This shadows the built-in name, and they're often handy to have around, e.g. dict(zip(keys, values)).)
You can use a tuple as a key (as long as all of its items are hashable):
>>> a = (1,2,3)
>>> b = {a:'hi'}
>>> b[(1,2,3)]
'hi'
>>>
Your problem is that you are trying to index the built-in function dict:
>>> dict
<type 'dict'>
>>>
dict is a type. You want to make an instance of that type.
d = {}
a = (1, 2, 3)
d[a] = 'hi'

Is there a Python dict without values?

Instead of this:
a = {"foo": None, "bar": None}
Is there a way to write this?
b = {"foo", "bar"}
And still let b have constant time access (i.e. not a Python set, which cannot be keyed into)?
Actually, in Python 2.7 and 3.2+, this really does work:
>>> b = {"foo", "bar"}
>>> b
set(['foo', 'bar'])
You can't use [] access on a set ("key into"), but you can test for inclusion:
>>> 'x' in b
False
>>> 'foo' in b
True
Sets are as close to value-less dictionaries as it gets. They have average-case constant-time access, require hashable objects (i.e. no storing lists or dicts in sets), and even support their own comprehension syntax:
{x**2 for x in xrange(100)}
Yes, sets:
set() -> new empty set object
set(iterable) -> new set object
Build an unordered collection of unique elements.
Related: How is set() implemented?
Time complexity : https://wiki.python.org/moin/TimeComplexity#set
In order to "key" into a set in constant time use in:
>>> s = set(['foo', 'bar', 'baz'])
>>> 'foo' in s
True
>>> 'fork' in s
False

Categories

Resources