Any way to use a tuple as key in a shelf? (Python) - python

I want to use a tuple (1,2,3) as a key using the shelve module in Python. I can do this with dictionaries:
d = {}
d[(1,2,3)] = 4
But if i try it with shelve:
s = shelve.open('myshelf')
s[(1,2,3)] = 4
I get: "TypeError: String or Integer object expected for key, tuple found"
Any suggestions?

How about using the repr() of the tuple:
s[repr((1,2,3))] = 4

As per the docs,
the values (not the keys!) in a shelf
can be essentially arbitrary Python
objects
My emphasis: shelf keys must be strings, period. So, you need to turn your tuple into a str; depending on what you'll have in the tuple, repr, some separator.join, pickling, marshaling, etc, may be fruitfully employed for that purpose.

Why not stick with dictionaries if you want to have arbitray keys ? The other option is to build a wrapper class around your tuple with a repr or str method to change it to a string. I am thinking of a library(natural response to shelves) - your tuple can be the elements in the Dewey decimal and the str creates a concatenated complete representation.

This may be an old question, but I had the same problem.
I often use shelve's and frequently want to use non-string keys.
I subclassed shelve-modules class into a shelf which automatically converts non-string-keys into string-keys and returns them in original form when queried.
It works well for Python's standard immutable objects: int, float, string, tuple, boolean.
It can be found in: https://github.com/North-Guard/simple_shelve

Related

How to map int to a list in redis?

I want to map numbers to list in redis
I currently have: r.set(r_id, [d_id,l_id,in_state], ex=10)
But it says this while running: Invalid input of type: 'list'. Convert to a bytes, string, int or float first.
Here I want to map: r_id -> [d_id,l_id,in_state]
how do i do this?
As you notice, SET doesn't accept list as value, but only simple values.
To work with lists, you should use the list-based commands.
Specifically, to map a key to a list, you can use the RPUSH command (note that it appends elements if the list already exists).
You haven't mentioned what client you use. Assuming it's redis-py, you would do:
r.rpush(r_id, d_id, l_id, in_state)
See documentation here.
You can find more information about Redis lists here.

How can I type multiple values returned from a method? [duplicate]

How do I use type hints to annotate a function that returns an Iterable that always yields two values: a bool and a str? The hint Tuple[bool, str] is close, except that it limits the return value type to a tuple, not a generator or other type of iterable.
I'm mostly curious because I would like to annotate a function foo() that is used to return multiple values like this:
always_a_bool, always_a_str = foo()
Usually functions like foo() do something like return a, b (which returns a tuple), but I would like the type hint to be flexible enough to replace the returned tuple with a generator or list or something else.
You are always returning one object; using return one, two simply returns a tuple.
So yes, -> Tuple[bool, str] is entirely correct.
Only the Tuple type lets you specify a fixed number of elements, each with a distinct type. You really should be returning a tuple, always, if your function produces a fixed number of return values, especially when those values are specific, distinct types.
Other sequence types are expected to have one type specification for a variable number of elements, so typing.Sequence is not suitable here. Also see What's the difference between lists and tuples?
Tuples are heterogeneous data structures (i.e., their entries have different meanings), while lists are homogeneous sequences. Tuples have structure, lists have order.
Python's type hint system adheres to that philosophy, there is currently no syntax to specify an iterable of fixed length and containing specific types at specific positions.
If you must specify that any iterable will do, then the best you can do is:
-> Iterable[Union[bool, str]]
at which point the caller can expect booleans and strings in any order, and of unknown length (anywhere between 0 and infinity).
Last but not least, as of Python 3.9, you can use
-> tuple[bool, str]
instead of -> Tuple[bool, str]; support for type hinting notation has been added to most standard-library container types (see PEP 585 for the complete list). In fact, you can use this as of Python 3.7 too provided you use the from __future__ import annotations compiler switch for your modules and a type checker that supports the syntax.

How to accept a database and print out a list in python

So I have to create a simple program that accepts a database with a bunch of artists and their works of art with the details of the art. There is a given artist and I have to search through the database to find all the ones where they have to same artist and return them. I'm not allowed to use other built in functions nor import anything. Can someone tell me why its creating the error and what it means?
def works_by_artists(db,artists):
newlist = {}
for a in db.keys():
for b in db[artists]:
if a == b:
newlist.append(a);
return newlist
This prints out an error:
for b in db[artists]:
TypeError: unhashable type: 'list'
A dictionary can accept only some kinds of values as keys. In particular, they must be hashable, which mean they cannot change while in the dictionary ("immutable"), and there must be a function known to Python that takes the value and returns a nonnegative integer that somehow represents the integer. Integers, floats, strings, and tuples are immutable and hashable, while standard lists, dictionaries, and sets are not. The hash value of the key is used to store the key-value pair in the standard Python dictionary. This method was chosen for the sake of speed of looking up a key, but the speed comes at the cost of limiting the possible key values. Other ways could have been chosen, but this works well for the dictionary's intended purpose in Python.
You tried to execute the line for b in db[artists]: while the current value of artists was not hashable. This is an error. I cannot say what the value of artists was, since the value was a parameter to the function and you did not show the calling code.
So check which value of artists was given to function works_by_artists() that caused the displayed error. Whatever created that value is the actual error in your code.

Can't convert string number value to float

I am working with a CSV file that contains 2 columns, the first a date column with format yyyymmdd, the second a string value that is in the format of a float, 0.0 for example.
import csv
file = open('Precipitation.csv')
date_file = csv.reader(file)
dec = 0.0
for k in date_file:
full_date = k[0]
month = full_date[4:-2]
rain_amount = k[1]
float(month)
if month == "12":
float(rain_amount)
dec += rain_amount
print(dec)
I keep checking the type of rain_amount by using type(rain_amount), and it keeps registering as "str." What am I doing wrong? I keep trying to check and do different things but I can't find out the problem. I am definitely doing something wrong, but I have been looking at this too long to figure it out. Help?
float() doesn't modify a variable in-place, it returns the new typed value. Assign it back:
rain_amount = float(rain_amount)
The float() function does not change its argument - it calculates the appropriate floating-point number required and returns that as a new object, so you have to save that somewhere if you want to use it. If you like, you can combine the float() call with the updating step, eg:
dec += float(rain_amount)
You may be wondering why Python works like that.
As mentioned in the Python Data model docs
An object’s type determines the operations that the object supports
(e.g., “does it have a length?”) and also defines the possible values
for objects of that type. The type() function returns an object’s type
(which is an object itself). Like its identity, an object’s type is
also unchangeable.
[Footnote] It is possible in some cases to change an object’s type, under certain
controlled conditions. It generally isn’t a good idea though, since it
can lead to some very strange behaviour if it is handled incorrectly.
So in general it's best to think of the type of an object as unchangeable. We may casually speak of converting a string to a float, but that's really just a sloppy way of saying that we are creating a float object with a numerical value that corresponds to the string object's contents.
Not only can't you change an object's type, for many basic Python object types you can't even change their value! Such objects are called immutable; common immutable types include all numeric types, strings, and tuples. Apart from tuples, most built-in container types (lists, dictionaries and sets (but not frozensets)) are mutable, meaning you can modify their contents.
So if you do
s = 'Sam'
s += 'my'
You aren't actually changing the string object s: you can't because it's immutable. Instead, a new string object is created that contains 'Sammy', that new object is then bound to the name s, and the old object that contained 'Sam' is discarded.
Similarly, if you do
a = 1
a += 1
a new integer object is created that has the value of a+1 and that new object is bound to the name a.
For more info on this topic, please see Facts and myths about Python names and values by SO veteran Ned Batchelder.
You are not storing the updated float type. You have to assign it back.
do this:
rain_amount=float(rain_amount)

What is a tuple useful for?

I am learning Python for a class now, and we just covered tuples as one of the data types. I read the Wikipedia page on it, but, I could not figure out where such a data type would be useful in practice. Can I have some examples, perhaps in Python, where an immutable set of numbers would be needed? How is this different from a list?
Tuples are used whenever you want to return multiple results from a function.
Since they're immutable, they can be used as keys for a dictionary (lists can't).
Tuples make good dictionary keys when you need to combine more than one piece of data into your key and don't feel like making a class for it.
a = {}
a[(1,2,"bob")] = "hello!"
a[("Hello","en-US")] = "Hi There!"
I've used this feature primarily to create a dictionary with keys that are coordinates of the vertices of a mesh. However, in my particular case, the exact comparison of the floats involved worked fine which might not always be true for your purposes [in which case I'd probably convert your incoming floats to some kind of fixed-point integer]
The best way to think about it is:
A tuple is a record whose fields don't have names.
You use a tuple instead of a record when you can't be bothered to specify the field names.
So instead of writing things like:
person = {"name": "Sam", "age": 42}
name, age = person["name"], person["age"]
Or the even more verbose:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
person = Person("Sam", 42)
name, age = person.name, person.age
You can just write:
person = ("Sam", 42)
name, age = person
This is useful when you want to pass around a record that has only a couple of fields, or a record that is only used in a few places. In that case specifying a whole new record type with field names (in Python, you'd use an object or a dictionary, as above) could be too verbose.
Tuples originate from the world of functional programming (Haskell, OCaml, Elm, F#, etc.), where they are commonly used for this purpose. Unlike Python, most functional programming languages are statically typed (a variable can only hold one type of value, and that type is determined at compile time). Static typing makes the role of tuples more obvious. For example, in the Elm language:
type alias Person = (String, Int)
person : Person
person = ("Sam", 42)
This highlights the fact that a particular type of tuple is always supposed to have a fixed number of fields in a fixed order, and each of those fields is always supposed to be of the same type. In this example, a person is always a tuple of two fields, one is a string and the other is an integer.
The above is in stark contrast to lists, which are supposed to be variable length (the number of items is normally different in each list, and you write functions to add and remove items) and each item in the list is normally of the same type. For example, you'd have one list of people and another list of addresses - you would not mix people and addresses in the same list. Whereas mixing different types of data inside the same tuple is the whole point of tuples. Fields in a tuple are usually of different types (but not always - e.g. you could have a (Float, Float, Float) tuple to represent x,y,z coordinates).
Tuples and lists are often nested. It's common to have a list of tuples. You could have a list of Person tuples just as well as a list of Person objects. You can also have a tuple field whose value is a list. For example, if you have an address book where one person can have multiple addresses, you could have a tuple of type (Person, [String]). The [String] type is commonly used in functional programming languages to denote a list of strings. In Python, you wouldn't write down the type, but you could use tuples like that in exactly the same manner, putting a Person object in the first field of a tuple and a list of strings in its second field.
In Python, confusion arises because the language does not enforce any of these practices that are enforced by the compiler in statically typed functional languages. In those languages, you cannot mix different kinds of tuples. For example, you cannot return a (String, String) tuple from a function whose type says that it returns a (String, Integer) tuple. You also cannot return a list when the type says you plan to return a tuple, and vice versa. Lists are used strictly for growing collections of items, and tuples strictly for fixed-size records. Python doesn't stop you from breaking any of these rules if you want to.
In Python, a list is sometimes converted into a tuple for use as a dictionary key, because Python dictionary keys need to be immutable (i.e. constant) values, whereas Python lists are mutable (you can add and remove items at any time). This is a workaround for a particular limitation in Python, not a property of tuples as a computer science concept.
So in Python, lists are mutable and tuples are immutable. But this is just a design choice, not an intrinsic property of lists and tuples in computer science. You could just as well have immutable lists and mutable tuples.
In Python (using the default CPython implementation), tuples are also faster than objects or dictionaries for most purposes, so they are occasionally used for that reason, even when naming the fields using an object or dictionary would be clearer.
Finally, to make it even more obvious that tuples are intended to be another kind of record (not another kind of list), Python also has named tuples:
from collections import namedtuple
Person = namedtuple("Person", "name age")
person = Person("Sam", 42)
name, age = person.name, person.age
This is often the best choice - shorter than defining a new class, but the meaning of the fields is more obvious than when using normal tuples whose fields don't have names.
Immutable lists are highly useful for many purposes, but the topic is far too complex to answer here. The main point is that things that cannot change are easier to reason about than things that can change. Most software bugs come from things changing in unexpected ways, so restricting the ways in which they can change is a good way to eliminate bugs. If you are interested, I recommend reading a tutorial for a functional programming language such as Elm, Haskell or Clojure (Elm is the friendliest). The designers of those languages considered immutability so useful that all lists are immutable there. (Instead of changing a list to add and or remove an item, you make a new list with the item added or removed. Immutability guarantees that the old copy of the list can never change, so the compiler and runtime can make the code perform well by re-using parts of the old list in the new one and garbage-collecting the left-over parts when they are longer needed.)
I like this explanation.
Basically, you should use tuples when there's a constant structure (the 1st position always holds one type of value and the second another, and so forth), and lists should be used for lists of homogeneous values.
Of course there's always exceptions, but this is a good general guideline.
Tuples and lists have the same uses in general. Immutable data types in general have many benefits, mostly about concurrency issues.
So, when you have lists that are not volatile in nature and you need to guarantee that no consumer is altering it, you may use a tuple.
Typical examples are fixed data in an application like company divisions, categories, etc. If this data change, typically a single producer rebuilts the tuple.
I find them useful when you always deal with two or more objects as a set.
A tuple is a sequence of values. The values can be any type, and they are indexed by integer, so tuples are not like lists. The most important difference is that tuples are immutable.
A tuple is a comma-separated list of values:
t = 'p', 'q', 'r', 's', 't'
it is good practice to enclose tuples in parentheses:
t = ('p', 'q', 'r', 's', 't')
A list can always replace a tuple, with respect to functionality (except, apparently, as keys in a dict). However, a tuple can make things go faster. The same is true for, for example, immutable strings in Java -- when will you ever need to be unable to alter your strings? Never!
I just read a decent discussion on limiting what you can do in order to make better programs; Why Why Functional Programming Matters Matters
A tuple is useful for storing multiple values.. As you note a tuple is just like a list that is immutable - e.g. once created you cannot add/remove/swap elements.
One benefit of being immutable is that because the tuple is fixed size it allows the run-time to perform certain optimizations. This is particularly beneficial when a tupple is used in the context of a return value or a parameter to a function.
Use Tuple
If your data should or does not need to be changed.
Tuples are faster than lists. We should use a Tuple instead of a List if we are defining a constant set of values and all we are ever going to do
with it is iterate through it.
If we need an array of elements to be
used as dictionary keys, we can use Tuples. As Lists are mutable,
they can never be used as dictionary keys.
Furthermore, Tuples are immutable, whereas Lists are mutable. By the same token, Tuples are fixed size in nature, whereas Lists are dynamic.
a_tuple = tuple(range(1000))
a_list = list(range(1000))
a_tuple.__sizeof__() # 8024 bytes
a_list.__sizeof__() # 9088 bytes
more information :
https://jerrynsh.com/tuples-vs-lists-vs-sets-in-python/
In addition to the places where they're syntactically required like the string % operation and for multiple return values, I use tuples as a form of lightweight classes. For example, suppose you have an object that passes out an opaque cookie to a caller from one method which is then passed into another method. A tuple is a good way to pack multiple values into that cookie without having to define a separate class to contain them.
I try to be judicious about this particular use, though. If the cookies are used liberally throughout the code, it's better to create a class because it helps document their use. If they are only used in one place (e.g. one pair of methods) then I might use a tuple. In any case, because it's Python you can start with a tuple and then change it to an instance of a custom class without having to change any code in the caller.
Tuples are used in :
places where you want your sequence of elements to be immutable
in tuple assignments
a,b=1,2
in variable length arguments
def add(*arg) #arg is a tuple
return sum(arg)

Categories

Resources