Python Object Oriented Programming - python

Am trying to understand object oriented programming with python. Am new to programming.
I have this class that is giving me an error I don't understand and I will be glad if anyone can throw more light on this for me:
class TimeIt(object):
def __init__(self, name):
self.name = name
def test_one(self):
print 'executed'
def test_two(self, word):
self.word = word
i = getattr(self, 'test_one')
for i in xrange(12):
sleep(1)
print 'hello, %s and %s:' % (self.word, self.name),
i()
j = TimeIt('john')
j.test_two('mike')
If I run this class I get 'int' object is not callable" TypeError
However, if I precede the i with self (self.i), it works.
class TimeIt(object):
def __init__(self, name):
self.name = name
def test_one(self):
print 'executed'
def test_two(self, word):
self.word = word
self.i = getattr(self, 'test_one')
for i in xrange(12):
sleep(1)
print 'hello, %s and %s:' % (self.word, self.name),
self.i()
My question is, doesn't i = getattr(self, 'test_one') assign the test_one function to i?
How come i() doesn't work?
Why does self.i() work?
Why is i an int (hence the 'int' object is not callable TypeError)?
That's a lot of questions. Thanks in advance

You're overwriting i within loop. When you're "preceding" i with self, you're creating different variable, which is not overwritten.

#SilentGhost is right on the money with his answer.
To illustrate, try chaning the test_two method to this:
def test_two(self, word):
self.word = word
i = getattr(self, 'test_one')
for some_other_variable_besides_i in xrange(12):
sleep(1)
print 'hello, %s and %s:' % (self.word, self.name),
i()
Your code overwrite the variable i (set as a method) within the for loop (see comments)
def test_two(self, word):
self.word = word
i = getattr(self, 'test_one')
# i is now pointing to the method self.test_one
for i in xrange(12):
# now i is an int based on it being the variable name chosen for the loop on xrange
sleep(1)
print 'hello, %s and %s:' % (self.word, self.name),
i()
In addition, you certainly don't need to assign the test_one method to a variable like i. Instead, you can just call the method replacing
i()
with
self.test_one()

Related

Python - print values not being returned by function

I'm learning about python at the moment and came across this code:
class Simple:
def __init__(self, str):
print("Inside the Simple constructor")
self.s = str
# Two methods:
def show(self):
print(self.s)
def showMsg(self, msg):
print(msg + ':',
self.show())
I'm playing around with it in the python shell and did the following:
x = Simple("A constructor argument")
x.show()
which outputs:
A constructor argument
This makes sense to me, however I then input:
x.showMsg("A message")
Which outputs:
A constructor argument
A Message:None
This is where I'm confused. Why is the call to the self.show() in showMsg() resulting in "None" when x.Show() results in "A constructor argument"? I thought that self was a placeholder until an instance of the class was created, which would mean that self.show() in this case would be equivalent to x.show()?
Any help on this would be very appreciated.
Get in the habit of having your functions return values. Functions with no return statement return None by default.
Here is an example of how you might rewrite your program:
class Simple:
def __init__(self, str):
self.s = str
# Two methods:
def show(self):
return self.s
def showMsg(self, msg):
return msg + ': ' + self.show()
x = Simple("A constructor argument")
print(x.show())
# A constructor argument
print(x.showMsg('A message'))
# A message: A constructor argument
While you can have print inside your class, it's a better idea to have your class handle logic and have flexibility with what you do with the results (print them, store them in a list, pass them on to another function, etc).
What the show() method in your class does is just print the stored message, however, what showMsg is trying to do concatenating some msg with the stored one, by calling the show method, however, since show() returns nothing, or None, it will get cat'ed just like that, you will have to change your method to either:
def show(self):
return self.s
or
def show(self):
print(self.s)
return self.s
In the second case you will retain the functionality for both cases, but it is bad practice

Python types.MethodType()

Why do I have to assign the result of types.MethodType() to an attribute before I use it via p.** in my example below. As I think, the method types.MethodType() has already bind the method onto the instance. Hope someone can help. Thanks a lot.
Here is my code:
import types
class Person(object):
def __init__(self, newName):
self.name = newName
def eat(self, food):
print("%s is eating %s" % (self.name, food))
def getName(self):
print("My name is %s" % self.name)
def main():
p = Person("Peter")
p.eat("Pork bean")
types.MethodType(getName, p) #p.getName = types.MethodType(getName, p)
p.getName()
if __name__ == "__main__":
main()
[]
[]
The following works to graft a method onto a class:
class A(object):
def __init__(self, value):
self.value = value
def my_method(self): # `self` is a plain name, not a reserved word or something.
return 'Value via a grafted method is %s' % self.value
A.grafted = my_method
assert A('here').grafted() == 'Value via a grafted method is here'
Yes, a plain assignment works.
Grafting a method onto an instance is harder but doable:
a = A('okay')
a.instance_patched = types.MethodType(my_method, a)
assert a.instance_patched() == 'Value via a grafted method is okay'
Here types.MethodType(my_method, a) creates a method bound to a.
Doing the following is elucidating:
print(my_method)
print(A.grafted)
print(a.instance_patched)
print(a.instance_patched.__func__) # in python 2.x, .im_func
Make sure that getName() is properly indented, on the same level as eat().
There is no need for types.MethodType() for you case:
class Person(object):
def __init__(self, newName):
self.name = newName
def eat(self, food):
print("%s is eating %s" % (self.name, food))
def getName(self):
print("My name is %s" % self.name)
def main():
p = Person("Peter")
p.eat("Pork bean")
p.getName()
if __name__ == "__main__":
main()
Output:
Peter is eating Pork bean
My name is Peter
Furthermore:
types.MethodType(getName, p)
does do anything useful, because you throw away the return value.
Because types.MethodType doesn't mutate either the function or the instance, it just returns a new callable object which holds both the function and the instance.
(You seem to have been expecting "bind" to mean "mutate one of the objects to hold a reference to the other", and so it sorta makes sense that you thought of it as adding the function onto the instance, but the best way to think of "bind" is that it produces a new function copy which has the instance bound as its first argument.)

Python: is there a way to "secretly" put text into a string?

I have been programming for about 2 months so I am relatively new to Python and programming in general.
I have a class with a field that will contain strings. I am trying to find a way to denote this string so that I can call it, but I don't want it to print the denotation. Is there a way to have a string contain text that won't be displayed when it is printed? This is what I mean by "secretly." I know I could make a separate field for this, and there are more complex ways to get around this, but I am wondering if the simple, easy process I am describing is possible.
So my use for this would be along the lines of:
class A(object):
def __init__(self, message):
self.message = message
x = A('\\magical marker\\this is a string.')
y = A("\\other magical marker\\this is a different string")
something = x # I am going to have a variable that could be many different things
if something.message.startswith('\\magical marker\\'):
print something
else:
pass
but when I print something, I want it to come out like this:
this is my string
sans the magical marker. Is there a way to do this?
You print something, which happens to be an instance of A. So you can define what happens when you try to print an object by defining a magic method __str__:
In [1]: class A:
...: def __init__(self, message):
...: self.message = message
...:
...: def __str__(self):
...: return self.message.split('}', 1)[-1]
...:
In [2]: x = A('{marker}my message')
In [3]: print(x)
my message
Note that printing x.message will print the whole string:
In [4]: x.message
Out[4]: '{marker}my message'
Changing that would be quite confusing.
How about re-programming the dot operator using properties.
class A(str):
def __init__(self, message):
self.message = message
#property
def message(self):
return 'this is my string'
#message.setter
def message(self, value):
self._message = value
x = A('\\magical marker\\this is a string.')
y = A("\\other magical marker\\this is a different string")
something = x
print x.message
This will always print 'this is my string' when you try to access the message field.
If you inherit from str you can simply str.replace:
class A(str):
def __init__(self, message):
self.message = message
x = A('\\magical marker\\this is a string.')
y = A("\\other magical marker\\this is a different string")
something = x # I am going to have a variable that could be many different things
if something.message.startswith('\\magical marker\\'):
print something.replace('\\magical marker\\',"",1)
A dirty little hack would be to use strings vs unicode strings:
x = 'this is a string.'
y = u'this is a unicode string.'
if isinstance(something, str):
print 'str'
else:
print 'unicode'
That only gets you two different classes, though. Maybe that's all you need?
Other answers have clever ideas that reveal interesting parts of Python... but miss the mark on matching your code to your goals, in a minimal and idiomatic way.
It sounds like the 'marker' is extra state that you want to remember and have affect later decisions.
So best would be to make that explicit: change your A class to accept another (probably optional) initialization argument:
class A(object):
def __init__(self, message, marker=None):
self.message = message
self.marker = marker
Then you later check the marker value directly and explicitly, without any 'hiding' or 'unpacking':
x = A('this is a string', marker='magic1')
if x.marker == 'magic1':
print x.message
else:
pass
This better describes the multifaceted nature of your A objects – even if their main purpose is carrying a string message, they've got other significant state, and it's good to give that state a distinctive name and place. You don't have to 'hide' it inside the main message – just give it its own slot.
(You might even move the conditional-logic, that determines what/whether to print, into another descriptively-named method on the A class – making instances of A responsible for their own display-rules.)
You could use something like this.
class SecretText(str):
def __str__(self):
"""Return empty string."""
return ''
def __repr__(self):
"""Return empty string."""
return self.__str__()
class SomewhatSecretText(str):
def __init__(self, *text):
"""Initialize a SomewhatSecretText instance."""
self.items = list(text)
assert self.verify_types()
# We have to keep some trace. Or we will
# never be able to get the original value.
self.message = ''.join(self.items)
def __str__(self):
"""Return string with hidden text."""
vis = ""
for item in self.items:
vis += str(item)
return vis
def __repr__(self):
"""Return string with hidden text."""
return self.__str__()
def __dir__(self):
"""
This is so self.message and self.items aren't
visible when dir() is called on the instance.
"""
return dir(str)
def verify_types(self):
"""Confirm instance items are strings."""
for item in self.items:
if not isinstance(item, str):
return False
return True
Using SomewhatSecretText, you can implement hidden text. Like this:
>>> hidden = SecretText("test")
>>> partly_hidden = SomewhatSecretText("This is a ", hidden, "!")
>>> print(partly_hidden)
This is a !
>>> print(repr(partly_hidden))
This is a !
>>> print(str(partly_hidden))
This is a !
You can get the full text back using the message variable.
>>> print(partly_hidden)
This is a !
>>> print(partly_hidden.message)
This is a test!
A bonus is that you can submit any number of strings to tag together. So you could have multiple hidden pieces.

Procedurally created decorator functions

My goal is to create a function that will procedurally generate a series of other functions within a class from serialized data.
This is easy enough using dict , but...
i would like for each function to be initialized with the #property decorator (or a similar custom decorator) so that i can call these functions like attributes
Basically, I would like to do something like the following:
class myClass(object):
def __init__(self):
self.makeFuncs(['edgar','allan','poe'])
def makeFuncs(self, data):
for item in data:
self.__dict__[item] = '[%s] <--- is_the_data' % item
myInstance = myClass()
print myInstance.poe
#'[poe] <--- is_the_data'
Got any Ideas?
You can dynamically add propertys, but properties are added to the class object, not the instance.
Here's an example:
def make_prop(cls, p):
def f(self):
print 'IN %s' % p
return '[%s]' % p
return f
class myClass(object):
pass
# add the properties
for p in ('edgar','allan','poe'):
setattr(myClass, p, property(make_prop(myClass, p)))
y = myClass()
print y.a
print y.b
Prints:
IN allan
[allan]
IN poe
[poe]
Also, it is essential to use make_prop to create the function object, instead of creating them directly inside the for loop, due to python's lexical scoping. I.e. this won't work as expected:
# add the properties
for p in ('edgar','allan','poe'):
def f(self):
print 'IN %s' % p
return '[%s]' % p
setattr(myClass, p, property(f))
Here is the answer I came to for procedurally adding properties to a custom shader class in maya.
Thx #shx2 !
import maya.cmds as mc
import sushi.maya.node.dependNode as dep
class Shader(dep.DependNode):
def __init__(self, *args, **kwargs):
super(Shader, self).__init__(*args, **kwargs)
makeProps(self.__class__, ['color','transparency','ambientColor','incandescence','diffuse','translucence','translucenceDepth','translucenceFocus'])
def createShaderProperties(attrName):
def getterProp(self):
return mc.getAttr('%s.%s' % (self.name, attrName))[0]
def setterProp(self, value):
mc.setAttr('%s.%s' % (self.name, attrName), *value, type = 'double3')
return (getterProp, setterProp)
def makeProps(cls, data):
for dat in data:
getterProp, setterProp = createShaderProperties(dat)
setattr(cls, dat, property(getterProp))
setattr(cls, dat, property.setter(cls.__dict__[dat],setterProp))
Your current idea won't work because property objects need to be in the class in order to work (they are descriptors). Since your list of functions is specific to each instance, that won't be possible.
However, you can make the general idea work using __getattr__. Here's an implementation that I think does what you want given a dictionary mapping from names to functions:
class MyClass(object):
def __init__(self, func_dict):
self.func_dict = func_dict
def __getattr__(self, name):
if name in self.func_dict:
return self.func_dict[name]() # call the function
raise AttributeError("{} object has no attribute named {}"
.format(self.__class__.__name__, name)) # or raise an error

Dynamically assigning function implementation in Python

I want to assign a function implementation dynamically.
Let's start with the following:
class Doer(object):
def __init__(self):
self.name = "Bob"
def doSomething(self):
print "%s got it done" % self.name
def doItBetter(self):
print "Done better"
In other languages we would make doItBetter an anonymous function and assign it to the object. But no support for anonymous functions in Python. Instead, we'll try making a callable class instance, and assign that to the class:
class Doer(object):
def __init__(self):
self.name = "Bob"
class DoItBetter(object):
def __call__(self):
print "%s got it done better" % self.name
Doer.doSomething = DoItBetter()
doer = Doer()
doer.doSomething()
That gives me this:
Traceback (most recent call last): Line 13, in
doer.doSomething() Line 9, in call
print "%s got it done better" % self.name AttributeError: 'DoItBetter' object has no attribute 'name'
Finally, I tried assigning the callable to the object instance as an attribute and calling it:
class Doer(object):
def __init__(self):
self.name = "Bob"
class DoItBetter(object):
def __call__(self):
print "%s got it done better" % self.name
doer = Doer()
doer.doSomething = DoItBetter()
doer.doSomething()
This DOES work as long as I don't reference self in DoItBetter, but when I do it gives me an name error on self.name because it's referencing the callable's self, not the owning class self.
So I'm looking for a pythonic way to assign an anonymous function to a class function or instance method, where the method call can reference the object's self.
Your first approach was OK, you just have to assign the function to the class:
class Doer(object):
def __init__(self):
self.name = "Bob"
def doSomething(self):
print "%s got it done" % self.name
def doItBetter(self):
print "%s got it done better" % self.name
Doer.doSomething = doItBetter
Anonymous functions have nothing to do with this (by the way, Python supports simple anonymous functions consisting of single expressions, see lambda).
yak's answer works great if you want to change something for every instance of a class.
If you want to change the method only for a particular instance of the object, and not for the entire class, you'd need to use the MethodType type constructor to create a bound method:
from types import MethodType
doer.doSomething = MethodType(doItBetter, doer)

Categories