I created a class Demo in which I added a constructor with an empty dictionary in it. With the method addSomething inside the class I add key value pairs to this dictionary. The key which gets added is of type str and the value of type int. In another method useKeys in the same class I wanna access the key which I added to the dictionary. With the keys() method I only get the key like dict_keys([<__main__.Demo object at 0x7f7cd00c75b0>]). How can I make the str who was added visible?
Code
class Demo:
def __init__(self, someString):
self.something = dict()
def addSomething(self, something):
if something not in self.something:
self.something[something] = 0
self.something[something] += 1
def useKeys(self):
#prints dict_keys([<__main__.Demo object at 0x7f7cd00c75b0>])
print(self.something.keys())
something1 = Demo("ABC")
something2 = Demo("DEF")
something1.addSomething(something2)
print(something1.useKeys())
Edit
One suggestion in the comments is to use __str__. I understand that this method gets called always if an object from this class gets printed. But how can I make the key from the dictionary readable? My current implementation does not make the key readable:
def __str__(self):
return "{self.something}".format(self=self)
With the method addSomething inside the class I add key value pairs to this dictionary. The key which gets added is of type str and the value of type int.
No, it is not. The key which gets added is of type Demo and the value is of type int. This is why printing the dictionary keys is printing the __repr__ of a Demo object.
How can I make the str who was added visible?
You did not add any str. The strings passed as arguments in your code are never used.
You can either write the __repr__ function (which will override the object object function of the same name, from which every python3 class inherits), or you can use the argument someString you're already providing and that it's not being used at all, it's only forcing you to provide a string when creating a new instance of a Demo object:
Solution 1
Actually using the attribute someString from the constructor in the addSomething function.
With this solution, the key is indeed of the type str.
class Demo:
def __init__(self, someString):
self.something = dict()
self.someString = someString # Actually using the string provided at instance time
def addSomething(self, something):
## This method will use the attribute someString from object something instead
if something.someString not in self.something:
self.something[something.someString] = 0
self.something[something.someString] += 1
def useKeys(self):
## keys are now strings
print(self.something.keys())
something1 = Demo("ABC")
something2 = Demo("DEF")
something1.addSomething(something2)
print(something1.useKeys())
Solution 2
Overriding __repr__, but you require a string anyway so using someString from the constructor too.
With this solution, the key is of type Demo, but when you print that key, it'll display a string.
class Demo:
def __init__(self, someString):
self.something = dict()
self.someString = someString # Actually using the string provided at instance time
def addSomething(self, something):
## This method will use the something object as in the original code
if something not in self.something:
self.something[something] = 0
self.something[something] += 1
def __repr__(self):
## When something1.__repr__ is called, it'll display the someString provided at instance time
return self.someString
def useKeys(self):
## keys are objects, but will appear as strings because of the __repr__ method from that object
print(self.something.keys())
something1 = Demo("ABC")
something2 = Demo("DEF")
something1.addSomething(something2)
print(something1.useKeys())
The __str__ function of an object is used in another circumstance, it's not needed in your requirement.
You can just convert it into a list for easy representation:
print(list(something1.useKeys()))
By the way, it does seem like the class you're implementing already exists as collections.Counter.
Related
I've been learning about classes in python and I was trying to write a reverse method for an extended string class, which looks like:
class NewString(str):
def reverse(self):
self = self[::-1]
string = NewString('Python')
string.reverse()
print(string)
I expected it to print 'nohtyP' but it doesn't. It keeps the original value of the string and prints 'Python'. Can anyone explain to me why this doesn't work and how I could change the class to get it to do what I expected. There is no purpose for this other than learning more about how classes work.
self is just a local variable in the method. Reassigning it won't mutate the object it referred to before. Since strings are immutable, so are objects of your string subclass. All you can do is return new string objects from the methods:
class NewString(str):
def reverse(self):
return self.__class__(self[::-1]) # casts to the specific type of self
string = NewString('Python')
rev = string.reverse()
print(rev)
# nohtyP
type(rev)
# NewString
I do understand how setattr() works in python, but my question is when i try to dynamically set an attribute and give it an unbound function as a value, so the attribute is a callable, the attribute ends up taking the name of the unbound function when i call attr.__name__ instead of the name of the attribute.
Here's an example:
I have a Filter class:
class Filter:
def __init__(self, column=['poi_id', 'tp.event'], access=['con', 'don']):
self.column = column
self.access = access
self.accessor_column = dict(zip(self.access, self.column))
self.set_conditions()
def condition(self, name):
# i want to be able to get the name of the dynamically set
# function and check `self.accessor_column` for a value, but when
# i do `setattr(self, 'accessor', self.condition)`, the function
# name is always set to `condition` rather than `accessor`
return name
def set_conditions(self):
mapping = list(zip(self.column, self.access))
for i in mapping:
poi_column = i[0]
accessor = i[1]
setattr(self, accessor, self.condition)
In the class above, the set_conditions function dynamically set attributes (con and don) of the Filter class and assigns them a callable, but they retain the initial name of the function.
When i run this:
>>> f = Filter()
>>> print(f.con('linux'))
>>> print(f.con.__name__)
Expected:
linux
con (which should be the name of the dynamically set attribute)
I get:
linux
condition (name of the value (unbound self.condition) of the attribute)
But i expect f.con.__name__ to return the name of the attribute (con) and not the name of the unbound function (condition) assigned to it.
Can someone please explain to me why this behaviour is such and how can i go around it?
Thanks.
function.__name__ is the name under which the function has been initially defined, it has nothing to do with the name under which it is accessed. Actually, the whole point of function.__name__ is to correctly identify the function whatever name is used to access it. You definitly want to read this for more on what Python's "names" are.
One of the possible solutions here is replace the static definition of condition with a closure:
class Filter(object):
def __init__(self, column=['poi_id', 'tp.event'], access=['con', 'don']):
self.column = column
self.access = access
self.accessor_column = dict(zip(self.access, self.column))
self.set_conditions()
def set_conditions(self):
mapping = list(zip(self.column, self.access))
for column_name, accessor_name in mapping:
def accessor(name):
print("in {}.accessor '{}' for column '{}'".format(self, accessor_name, column_name))
return name
# this is now technically useless but helps with inspection
accessor.__name__ = accessor_name
setattr(self, accessor_name, accessor)
As a side note (totally unrelated but I thought you may want to know this), using mutable objects as function arguments defaults is one of the most infamous Python gotchas and may yield totally unexpected results, ie:
>>> f1 = Filter()
>>> f2 = Filter()
>>> f1.column
['poi_id', 'tp.event']
>>> f2.column
['poi_id', 'tp.event']
>>> f2.column.append("WTF")
>>> f1.column
['poi_id', 'tp.event', 'WTF']
EDIT:
thank you for your answer, but it doesn't touch my issue here. My problem is not how functions are named or defined, my problem it that when i use setattr() and i set an attribute and i give it a function as it's value, i can access the value and perform what the value does, but since it's a function, why doesn't it return it's name as the function name
Because as I already explained above, the function's __name__ attribute and the name of the Filter instance attribute(s) refering to this function are totally unrelated, and the function knows absolutely nothing about the names of variables or attributes that reference it, as explained in the reference article I linked to.
Actually the fact that the object you're passing to setattr is a function is totally irrelevant, from the object's POV it's just a name and an object, period. And actually the fact you're binding this object (function or just whatever object) to an instance attribute (whether directly or using setattr(), it works just the same) instead of a plain variable is also totally irrelevant - none of those operation will have any impact on the object that is bound (except for increasing it's ref counter but that's a CPython implementation detail - other implementations may implement garbage collection diffently).
May I suggest you this :
from types import SimpleNamespace
class Filter:
def __init__(self, column=['poi_id', 'tp.event'], access=['con', 'don']):
self.column = column
self.access = access
self.accessor_column = dict(zip(self.access, self.column))
self.set_conditions()
def set_conditions(self):
for i in self.access:
setattr(self, i, SimpleNamespace(name=i, func=lambda name: name))
f = Filter()
print(f.con.func('linux'))
>>> linux
print(f.con.name)
>>> con
[edited after bruno desthuilliers's comment.]
I am making a derived variant of the dict class such that a dictionary value can be accessed through attribute access syntax (so instead of doing dictionary['foo'] you could do dictionary.foo.) This is what I have so far:
class dict(dict):
__getattr__ = dict.__getitem__
However, this snippet of my code gives it problems:
eventD = {'rrule_end':None}
. . .
. . .
#(some time later)
print event.rrule_end
This is because the { } operators for dictionary creation have not been overloaded. Is it possible to make the dictName = { } syntax create an instance of my derived class instead of an ordinary dictionary?
No. You cannot override dict literal syntax. (You also can't override list literal syntax, or string literal syntax, or number literal syntax, or any literal syntax.)
You have to create the instance of your class explicitly. Give your class a name like MyDict and then do
eventD = MyDict({'rrule_end':None})
no, you can't overload that syntax, but their are alternative things you can do.
convert a normal dictionary into your dictionary
my_dict( {'foo':bar, 'foo2':bar2} )
make your function accept key-args
my_dict( foo='bar', foo2='bar2' )
make up your own syntax for this dictionary.
this is abusing python's overloadable operators and is a little complex to do.
its a chain reaction, starting with my_dict<'foo'.
overload the operator so it outputs another my_dict object and repeat the process,
each time keeping a record of each value until if finally reaches the end object.
then it calculates and spits out you own object object.
my_dict<'foo'|bar,'foo2'|'bar2'>end
EDIT:
I'm not sure the reason you want to do this, but this could be an alternative answer to your problem. you may also want to have a look at the vars built in function. this lets you get a dictionary of every attribute an object has. if the object changes, the dictionary changes automatically.
class dict_obj(object):
def __init__(self, obj):
self.obj = obj
self.dict = vars(obj)
def __getattr__(self, value):
return self.dict[value]
__getitem__ = __getattr__
you can use it like this
>>> class test:
def __init__(self):
self.value = 5
>>> obj = dict_obj(test())
>>> obj.value
5
>>> obj['value']
5
I am trying to write a wrapper object around the dictionary object in python like so
class ScoredList():
def __init__(self,dct={}):
self.dct = dct
list = ScoredList()
list.dct.update({1,2})
list2 = ScoredList()
list.dct.update({"hello","world"})
print list1.dct, list2.dct # they are the same but should not be!
It seems like I am unable to create a new ScoredList object, or rather, every scored list object shares the same underlying dictionary. Why is this?
class ScoredList2():
def __init__(self):
self.dct = {}
The above code for ScoredList2 works fine. But I want know how to overload the constructor properly in python.
A dictionary is a mutable object. In Python, default values are parsed when the function is created, meaning the same empty dictionary is assigned to every new object.
To solve this, simply do something like:
class ScoredList():
def __init__(self, dct=None):
self.dct = dct if dct is not None else {}
I have a class, and I would like to be able to create multiple objects of that class and place them in an array. I did it like so:
rooms = []
rooms.append(Object1())
...
rooms.append(Object4())
I then have a dict of functions, and I would like to pass the object to the function. However, I'm encountering some problems..For example, I have a dict:
dict = {'look': CallLook(rooms[i])}
I'm able to pass it into the function, however; in the function if I try to call an objects method it gives me problems
def CallLook(current_room)
current_room.examine()
I'm sure that there has to be a better way to do what I'm trying to do, but I'm new to Python and I haven't seen a clean example on how to do this. Anyone have a good way to implement a list of objects to be passed into functions? All of the objects contain the examine method, but they are objects of different classes. (I'm sorry I didn't say so earlier)
The specific error states: TypeError: 'NoneType' object is not callable
Anyone have a good way to implement a list of objects to be passed into functions? All of the objects contain the examine method, but they are objects of different classes. (I'm sorry I didn't say so earlier)
This is Python's plain duck-typing.
class Room:
def __init__(self, name):
self.name = name
def examine(self):
return "This %s looks clean!" % self.name
class Furniture:
def __init__(self, name):
self.name = name
def examine(self):
return "This %s looks comfortable..." % self.name
def examination(l):
for item in l:
print item.examine()
list_of_objects = [ Room("Living Room"), Furniture("Couch"),
Room("Restrooms"), Furniture("Bed") ]
examination(list_of_objects)
Prints:
This Living Room looks clean!
This Couch looks comfortable...
This Restrooms looks clean!
This Bed looks comfortable...
As for your specific problem: probably you have forgotten to return a value from examine()? (Please post the full error message (including full backtrace).)
I then have a dict of functions, and I would like to pass the object to the function. However, I'm encountering some problems..For example, I have a dict:
my_dict = {'look': CallLook(rooms[i])} # this is no dict of functions
The dict you have created may evaluate to {'look': None} (assuming your examine() doesn't return a value.) Which could explain the error you've observed.
If you wanted a dict of functions you needed to put in a callable, not an actual function call, e.g. like this:
my_dict = {'look': CallLook} # this is a dict of functions
if you want to bind the 'look' to a specific room you could redefine CallLook:
def CallLook(current_room)
return current_room.examine # return the bound examine
my_dict = {'look': CallLook(room[i])} # this is also a dict of functions
Another issue with your code is that you are shadowing the built-in dict() method by naming your local dictionary dict. You shouldn't do this. This yields nasty errors.
Assuming you don't have basic problems (like syntax errors because the code you have pasted is not valid Python), this example shows you how to do what you want:
>>> class Foo():
... def hello(self):
... return 'hello'
...
>>> r = [Foo(),Foo(),Foo()]
>>> def call_method(obj):
... return obj.hello()
...
>>> call_method(r[1])
'hello'
Assuming you have a class Room the usual way to create a list of instances would be using a list comprehension like this
rooms = [Room() for i in range(num_rooms)]
I think there are some things you may not be getting about this:
dict = {'look': CallLook(rooms[i])}
This creates a dict with just one entry: a key 'look', and a value which is the result of evaluating CallLook(rooms[i]) right at the point of that statement. It also then uses the name dict to store this object, so you can no longer use dict as a constructor in that context.
Now, the error you are getting tells us that rooms[i] is None at that point in the programme.
You don't need CallLook (which is also named non-standardly) - you can just use the expression rooms[i].examine(), or if you want to evaluate the call later rooms[i].examine.
You probably don't need the dict at all.
That is not a must, but in some cases, using hasattr() is good... getattr() is another way to get an attribute off an object...
So:
rooms = [Obj1(),Obj2(),Obj3()]
if hasattr(rooms[i], 'examine'):#First check if our object has selected function or attribute...
getattr(rooms[i], 'examine') #that will just evaluate the function do not call it, and equals to Obj1().examine
getattr(rooms[i], 'examine')() # By adding () to the end of getattr function, we evalute and then call the function...
You may also pass parameters to examine function like:
getattr(rooms[i], 'examine')(param1, param2)
I'm not sure of your requirement, but you can use dict to store multiple object of a class.
May be this will help,
>>> class c1():
... print "hi"
...
hi
>>> c = c1()
>>> c
<__main__.c1 instance at 0x032165F8>
>>> d ={}
>>> for i in range (10):
... d[i] = c1()
...
>>> d[0]
<__main__.c1 instance at 0x032166E8>
>>> d[1]
<__main__.c1 instance at 0x032164B8>
>>>
It will create a object of c1 class and store it in dict. Obviously, in this case you can use list instead of dict.