Can I access a class without an __init__? - Python - python

I want to be able to print "hello harry" from a module. This is my module (called test23):
class tool:
def handle(self,name):
self.name = "hello " + name
This is my script:
import test23
harry= test23.tool().handle(" harry")
print harry.name
I can't seem to print "hello harry" inside my script idle. How would I go about doing this?

handle doesn't return anything, so harry will be NoneType.
Do it in two times: first assign the instance, then call the method:
>>> class tool:
... def hello(self,name):
... self.name="hello "+name
...
>>> a=tool()
>>> a.hello('i')
>>> a.name
'hello i'
>>> b=tool().hello('b')
>>> b.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
>>> type(b)
<type 'NoneType'>

I think this will do it.
from test23 import tool
harry = tool()
harry.handle("harry")
print harry.name

tool.handle() doesn't return an object, so you need to store the object before you call the method:
import test23
harry = test23.tool()
harry.handle("harry")
print harry.name

What you wanted to do is:
harry = test23.tool() # Ok harry is a tool object
harry.handle(" harry") # Ok harry.name has been set to " harry"
print harry.name # Ok print successfully "hello harry"
But what you did is: harry= test23.tool().handle(" harry")
Let's look one pass at a time:
test23.tool() : builds a new (temporary) tool object
test23.tool().handle(" harry") : sets the attribute name of the temporary and returns... None!
harry= test23.tool().handle(" harry") : sets the attribute name of a temporary tool object, set harry to the return value of the handle method which is None => same as harry = None
Alternatively, you should change handle to return the tool object:
class tool:
def handle(self,name):
self.name = "hello " + name
return self

Related

Get variable from a parent function

I have a function that produces another function.
def make_func(greeting):
def func(name):
return greeting + " " + name
return func
>>> say_hello = make_func("Hello")
>>> say_hello("there")
"Hello there"
Elsewhere in the script, I have access to say_hello, but I have no idea what the greeting in that function actually is. I'd like to find out.
name, of course, isn't possible to get because it's specified when the function is called. But greeting is static, because it's defined outside of the function.
Is there some attribute of say_hello I can examine to get the original "Hello"?
You can find a good explanation of how inner functions are compiled in python here
Then the easiest way to get the variable is say_hello.__closure__[0].cell_contents
You can just store the attribute greeting in func:
def make_func(greeting):
def func(name):
return func.greeting + " " + name
func.greeting = greeting
return func
say_hello = make_func("Hello")
print(say_hello.greeting) # Hello
say_hello.greeting = 'Bye'
print(say_hello('there')) # Bye there

print object name, when object call a function inside the class

#!/usr/bin/env python
class AA(object):
def __init__(self):
pass
def y(self):
pass
x=AA()
x.y()
When I execute x.y(), I want to print "This is 'x' call me", how should I do it ?
I hope that this will solve your issue
#!/usr/bin/env python
class AA(object):
def __init__(self):
pass
def y(self, name):
self.name = name
print("This is %s call me" % name)
x = AA()
x.y("Tarzan")
Everything is an object in Python, When you create an instance of the class it allocate memory location and that memory location is referenced by your x variable.The only object has memory location, variable doesn't have any memory location. Variable just refer to objects memory location
in your example, X is nothing just reference to your memory location
if define a variable
a = 2
that means a reference to 2
a = 1
that means a now reference to 1
Assigning one variable to another makes a new tag bound to the same value as shown below.
b = a
that means a and b both reference to 1
id() in python return memory location
print id(a)
print id(b)
output
140621897573617
140621897573617
Example 1:
>>> s1 = 'hello'
>>> s2 = 'hello'
>>> id(s1), id(s2)
(4454725888, 4454725888)
>>> s1 == s2 True
>>> s1 is s2 True
>>> s3 = 'hello, world!'
>>> s4 = 'hello, world!'
>>> id(s3), id(s4) (4454721608, 4454721664)
>>> s3 == s4 True
>>> s3 is s4 False
Example 2
>>> class Foo:
... pass
...
>>> bar = Foo()
>>> baz = Foo()
>>> id(bar)
140730612513248
>>> id(baz)
140730612513320
result
Name of object or instance is nothing just reference to memory
location
From #user1334609 's comment:
for example, we have lots of vm instance,vm1=AA(),
vm1.run_cmd("xxxx"), vm2=AA(), vm2.run_cmd("") I want to know which vm
are run some cmd
To know which VM has run the command you can just use the id(self), instead of trying to find the declared variable in code.
Two options you have now to see from which vm, command is running.
Option1: Add a member variable to class. This can give readability.
Option2: Use the id of self in y(). This avoids adding additional variable.
Example code:
#!/usr/bin/env python
class AA(object):
def __init__(self, vmname):
self.whoami = vmname
def y(self):
print "My Name is %s " % self.whoami # Option1
print "My Id is %s " % id(self) # Option2
def main():
vm1=AA("Yoda")
vm1.y()
vm2=AA("Boda")
vm2.y()
vm3=AA("Anakin")
vm3.y()
if __name__ == '__main__':
main()
This gives following output:
My Name is Yoda
My Id is 139725977256656
My Name is Boda
My Id is 139725977256720
My Name is Anakin
My Id is 139725977256784
I have posted a complete solution here:
https://stackoverflow.com/a/49331683/7386061
It works without parameters. For example you could just do:
class AA(RememberInstanceCreationInfo):
def y(self):
print("my name is '"+self.creation_name+"'")
x=AA()
x.y()
out: my name is 'x'

Python Jinja2 post

I just want to check if my elif statement is correct to check for content composed entirely of white-spaces. Thanks.
def post(self):
wall_name = self.request.get('wall_name',DEFAULT_WALL)
comment_container = CommentContainer(parent = wall_key(wall_name))
comment_container.name = self.request.get('name')
comment_container.content = self.request.get('content')
if comment_container.content == '':
self.redirect("/error")
elif comment_container.content == str.isspace:
self.redirect("/error")
else:
comment_container.put()
self.redirect('/#comment_section')
The isspace() function is an instance function and also a class function -- meaning you can call it on an existing string or by passing it an argument.
For example:
>>> 'foo' == str.isspace
False
>>> 'foo' == str.isspace()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor 'isspace' of 'str' object needs an argument
>>> str.isspace(' ')
True
The first line there appears to work correctly because str.isspace does indeed not equal the string 'foo', but this is because 'foo' is a string and str.isspace is a function. We never called isspace()!
>>> str.isspace
<method 'isspace' of 'str' objects>
See? That's its actual identity.
But we can call it over an existing string:
>>> 'foo'.isspace()
False
>>> ' foo '.isspace()
False
>>> ' '.isspace()
True
>>> foo = ' '
>>> bar = ' blahblah '
>>> foo.isspace()
True
>>> bar.isspace()
False
So you need to assign the thing you want to test first (you can reference it directly, but that will be annoying to read a few months from now when you want to maintain this code):
def post(self):
content = self.request.get('content')
if content == '' or content.isspace():
self.redirect('/error')
else:
wall_name = self.request.get('wall_name',DEFAULT_WALL)
comment_container = CommentContainer(parent = wall_key(wall_name))
comment_container.name = self.request.get('name')
comment_container.content = self.request.get('content')
comment_container.put()
self.redirect('/#comment_section')
Now we've saved the work you were throwing away and checked for blank comments.
One note, you could also call change the if check to this:
if self.request.get('content') == '' or content.isspace(self.request.get('content')):
But again, I find this less obvious and clear.
str.isspace() is a method, so you would probably want to use:
elif str.isspace(comment_container.content):
or
elif isspace(comment_container.content.isspace():

Python: creating a temporary name for a specific function

I'm learning Python. I'm reading some code containing something like this:
class Menu:
'''Display a menu and respond to choices when run.'''
def __init__(self):
self.notebook = Notebook()
self.choices = {
"1": self.show_notes,
"2": self.search_notes,
"3": self.add_note,
"4": self.modify_note,
"5": self.quit
}
def display_menu(self):
print("""
Notebook Menu
1. Show all Notes
2. Search Notes
3. Add Note
4. Modify Note
5. Quit
""")
def run(self):
"""Display the menu and respond to choices."""
while True:
self.display_menu()
choice = input("Enter an option: ")
action = self.choice.get(choice)
if action:
action()
else:
print("{0} is not a valid choice".format(choice))
def show_notes(self):
pass
def search_notes(self):
pass
def add_note(self):
pass
def modify_note(self):
pass
def quit(self):
pass
There are some lines very interesting:
action = self.choice.get(choice)
if action:
action()
Seems it's creating a temporary name for a specific function.
So I did the following test for it to learn more:
>>> def show_notes():
print("show notes")
>>> def search_notes():
print("search notes")
>>> choice = {"1": show_notes, "2": search_notes}
>>> action = choice.get(1)
>>> action()
But I get the following error:
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
action()
TypeError: 'NoneType' object is not callable
Can someone tell me what the technique is and what principle is behind?
Functions are first class objects, and you can create additional references to them. These are just as temporary as you need to them to be, but they can be permanent too.
Your own attempt confused strings and integers however; you used 1 (an integer) where the actual key is '1' (a string). Because you used the wrong key, the dict.get() method returned a default instead, None. None is not a function object and the call fails.
Had you used the right key your code would have worked too:
>>> def show_notes():
... print("show notes")
...
>>> def search_notes():
... print("search notes")
...
>>> choice = {"1": show_notes, "2": search_notes}
>>> choice['1']
<function show_notes at 0x10b1fae18>
>>> choice['1']()
show notes
You can make use of dict.get() returning a default here too, by giving the method a better default to return:
>>> choice.get('none-such-key', search_notes)()
search notes
It seems there's an error in your test. You should be getting "1" and not 1. Getting 1 is returning None because there's nothing defined for key 1. Therefore when you call it like a function it's not valid.
To clarify, "1" is a string and 1 is an integer, which are different keys.
Example:
>>> a = {"1": "yes"}
>>> a.get(1)
>>> a.get("1")
'yes'
Example II (using function):
>>> def hello():
... print "hello"
...
>>> hello()
hello
>>> a = {"1": hello}
>>> b = a.get(1)
>>> b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
>>> b = a.get("1")
>>> b()
hello
It's not creating a random name for a function. The class method choice is selecting a function and returning it, and it is subsequently being assigned to the variable action. The function is then called by calling action, like you would any function.
Here's an example:
def foo():
print(5)
def getFunction():
return foo
x = getFunction()
x()
The output from this will be 5.
Taking a step back from all of this, you can assign any object to any variable. So consider the following example (I think this will help you understand a little bit more):
def foo():
print(5)
bar = foo
foo = 5
foo()
This will produce an error along the lines of integer objects are not callable. The way this works is that the function object contained in foo is being assigned to variable bar, and the integer 5 is being assigned to foo. The function hasn't changed, but the variable containing it has.
The very first part of defining a function def foo is letting the interpreter know that you are defining a function object and storing in the variable foo. The name and the mechanics of the function are separate.
Does this make sense?

Does python allow calling of an instance variable name from an instance method?

I want to know if there is a way in python to call the name of an instance variable? For example, if I define a class
>>>class A(object):
... def get_instance_name(self):
... return # The name of the instance variable
>>>obj = A()
>>>obj.get_instance_name()
obj
>>>blah = A()
>>>blah.get_instance_name()
blah
Raise an exception. Not only is it the appropriate way to signal an error, it's also more useful for debugging. The traceback includes the line which did the method call but also additional lines, line numbers, function names, etc. which are more useful for debugging than just a variable name. Example:
class A:
def do(self, x):
if x < 0:
raise ValueError("Negative x")
def wrong(a, x):
a.do(-x)
wrong(A(), 1)
This gives a traceback similar to this, if the exception isn't caught:
Traceback (most recent call last):
File "...", line 1, in <module>
wrong(A(), 1)
File "...", line 7, in wrong
a.do(-x)
File "...", line 4, in do
raise ValueError("Negative x")
ValueError: Negative x
You can also use the traceback module to get this information programmatically, even without an exception (print_stack and friends).
globals() return a dictionary that represents the namespace of the module (the namespace is not this dictionary, this latter only represents it)
class A(object):
def get_instance_name(self):
for name,ob in globals().iteritems():
if ob is self:
return name
obj = A()
print obj.get_instance_name()
blah = A()
print blah.get_instance_name()
tu = (obj,blah)
print [x.get_instance_name() for x in tu]
result
obj
blah
['obj', 'blah']
.
EDIT
Taking account of the remarks, I wrote this new code:
class A(object):
def rondo(self,nameinst,namespace,li,s,seen):
for namea,a in namespace.iteritems():
if a is self:
li.append(nameinst+s+namea)
if namea=='__builtins__':
#this condition prevents the execution to go
# in the following section elif, so that self
# isn't searched among the cascading attributes
# of the builtin objects and the attributes.
# This is to avoid to explore all the big tree
# of builtin objects and their cascading attributes.
# It supposes that every builtin object has not
# received the instance, of which the names are
# searched, as a new attribute. This makes sense.
for bn,b in __builtins__.__dict__.iteritems():
if b is self:
li.append(nameinst+'-'+b)
elif hasattr(a,'__dict__') \
and not any(n+s+namea in seen for n in seen)\
and not any(n+s+namea in li for n in li):
seen.append(nameinst+s+namea)
self.rondo(nameinst+s+namea,a.__dict__,li,'.')
else:
seen.append(nameinst+s+namea)
def get_instance_name(self):
li = []
seen = []
self.rondo('',globals(),li,'')
return li if li else None
With the following
bumbum = A()
blah = A()
print "bumbum's names:\n",bumbum.get_instance_name()
print "\nmap(lambda y:y.get_instance_name(), (bumbum,blah) :\n",map(lambda y:y.get_instance_name(), (bumbum,blah))
print "\n[y.get_instance_name() for y in (bumbum,blah)] :\n",[y.get_instance_name() for y in (bumbum,blah)]
the result is
bumbum's names:
['bumbum']
map(lambda y:y.get_instance_name(), (bumbum,blah) :
[['bumbum'], ['blah']]
[y.get_instance_name() for y in (bumbum,blah)] :
[['bumbum', 'y'], ['blah', 'y']]
The second list comprehension shows that the function get_instance_name() must be used with care. In the list comp, identifier y is assigned in turn to every element of (bumbum,blah) then the finction finds it out as a name of the instance !
.
Now, a more complex situation:
ahah = A() # ahah : first name for this instance
class B(object):
pass
bobo = B()
bobo.x = ahah # bobo.x : second name for ahah
jupiter = bobo.x # jupiter : third name for ahah
class C(object):
def __init__(self):
self.azerty = jupiter # fourth name for ahah
ccc = C()
kkk = ccc.azerty # kkk : fifth name for ahah
bobo.x.inxnum = 1005
bobo.x.inxwhat = kkk # bobo.x.inxwhat : fifth name for ahah
# Since bobo.x is instance ahah, this instruction also
# creates attribute inxwhat in ahah instance's __dict__ .
# Consequently, instance ahah having already 5 names,
# this instruction adds 5 additional names, each one
# ending with .inxwhat
# By the way, this kkk being ahah itself, it results that ahah
# is the value of its own attribute inxwhat.
print ahah.get_instance_name()
result
['bobo.x', 'bobo.x.inxwhat',
'ahah', 'ahah.inxwhat',
'jupiter', 'jupiter.inxwhat',
'kkk', 'kkk.inxwhat',
'ccc.azerty', 'ccc.azerty.inxwhat']
I concur to judge this solution a little heavy and that if a coder thinks he needs such a heavy function, it is probably because the algorithm isn't optimal. But I find interesting to see that it's possible to do this in Python though it doesn't seem evident.
I say heavy, not hacky, I don't find it's hacky, by the way.
No, you can't. Objects can have any number of names, so the question doesn't even make sense. Consider:
a1 = a2 = a3 = A()
What is the name of the instance of A()?

Categories