I am trying to create a class that can be given any object on construction and then will list all of that object's callable methods in an interactive prompt. I am using the PyInquirer module for the interactive prompt, and the inspect module to get all the methods of the given object.
I have so far succeeded in dynamically building the prompt for any given object, but my program gives the error Foo() takes 0 positional arguments but 1 was given when attempting to call one of the methods from the prompt.
I think the reason it crashes is that at the time of execution there are no more references to the object, so its reference count is at zero and the object is freed.
If I could get the class to keep hold of its own reference to the object, then this will solve the problem. For example
def __init__(self, object):
# Create a local reference the object
self.__object = &object
But this is invalid python.
How do I get a reference to the object (or manually increment the reference count, and manually decrement it in the __del__ function)?
Full source code for ObjectMethodTerminal.py can be found here https://gitlab.com/snippets/1939696
Change your sample class to this:
class A:
def Foo(self):
print("Hello")
def Bar(self):
print("World")
def Baz(self):
print("!")
Note the added self to the method parameters.
If you had tried this code first:
a = A()
a.Foo()
You would have found your error before going the long route of inspecting the class.
Related
I've a function that I want to write unit tests for (function is a part of class A):
def funcA(self):
variable = self.attributes.method()
logger.info("Log")
this function is called from another function that initialize Class and save its object to self.attributes variable.
def funcB(self):
self.attributes = B()
# call funcA if certain criteria is met
and I have implementation of method function inside of B class definition.
How can I now write unit test for funcA?
I've tried to do it like this:
import classA as a
def test_funcA(self) -> None:
self.classA = a.A()
method_return = self.classA.funcA()
this gives me error 'A' object has no attribute 'attributes'
I also tried to mock this missing attribute by:
a.A.attributes = Mock(return_value={})
but then I got different error TypeError: Object of type Mock is not JSON serializable
I guess I need to somehow mock class B and the method function, so that my main method that I'm testing will just take the mocked return and assert if it logs correct message, right?
Your initial intuition about setting the attributes directly is probably the way to go. You should set the proper value - with the relevant properties B() would have returned.
Inside your test, you can do something in the form of self.classA.attributes = Bunch(mathod=lambda: "value for variable", another_attribute_used_inside_funcA = 20). See bunch library.
I was learning Python by using Python Crash Course and came upon this String and Method thing: It only said that the dot(.) after name in name.title() tells Python to make the title() method act on the variable name.
Not always, you can create a method dynamically:
from types import MethodType
def fn(x):
return x.var
class A:
def __init__(self):
self.var = 20
obj = A()
method_ = MethodType(fn, obj)
print(method_)
print(method_())
output :
<bound method fn of <__main__.A object at 0x000001C5E3F01FD0>>
20
A method is an instance of type MethodType and also it has an object bound to it, when method gets called, it's first parameter will always get filled with that object. Here fn() function's first parameter (x) will be filled with obj object.
The above answer is precise but i wanted to add to it.
Actually methods are functions that take objects as arguments and then return values based on that and as python is an Object Oriented Language therefore everything in python is an object.
When you call name.title():
then, python search for the title() method for the name object.And as all methods are designated to take the object as an argument:
`def title(self):
...+
`
This is what a method definition look like inside a class and the self argument here stands for the object calling the method.
And we do not have to specify it explicitly it is recognised by the python interpreter.
As in your case: name.title() the object calling the method title() is the name variable therefore here self is assigned the value of name that is the function call name.title() is equivalent to title(name) but the former is the correct syntax of calling the method whereas the latter one is for comprehesion purpose.
If you run title(name) it surely gonna raise an error.
But, as the title() method belongs to the str class you can always call str.title(name).
Hope i didn't confuse you instead of making it clearer...Happy coding..:)
All. I understand that when you call a method which does not belong to that object, you will get an error, saying that "list object does not have that attribute". My question is: why does people use attributes here, instead of using methods? I mean, precisely speaking, it should be methods, right? Thank you all.
In an operation like
some_list.foo()
there are two steps you're thinking of as one. Retrieve the attribute:
some_list.foo
and call it:
()
Unlike in some other languages, these are completely independent steps. The code responsible for the some_list.foo attribute access doesn't know that you're planning to call the attribute. It just sees that you're trying to retrieve an attribute that doesn't exist, and that's what it tells you.
A method is an attribute, specifically a callable one. Attribute is a more general term that includes anything scoped to an object. For instance:
class Example(object):
def __init__(self):
self.some_attr = True
def some_method(self):
return False
foo = Example()
foo.some_attr # is an attribute of foo of type boolean
foo.some_method # is an attribute of foo of type method
Because in Python there are no methods in general (methods are just functions attached to classes). Typical invocation looks like this:
x.foo (bar)
But this is exactly the same as this:
m = x.foo
m (bar)
The error happens at the first step, and it is clear that at this point foo is just an attribute, and attribute getter has no idea what will be done with it later.
Considering the following code:
class A:
def foo():
return "a"
a = A()
a.bar()
When calling a.bar() Python produce the following ast (Abstract Syntax Tree):
Call(
func=Attribute(
value=Name(id='a', ctx=Load()),
attr='bar',
ctx=Load()
),
# ...
)
The first thing Python tries to do is getting the attribute, and checking if it is callable. If the attribute does not exist, Attribute will fail first, resulting in its associated error A object has no attribute bar.
Notice it is not saying A object has no attribute bar()
So I know in python everything is an 'object' meaning that it can be passed as an argument to a method. But I'm trying to understand how exactly does this work. So I was trying out the following example:
class A:
def __init__(self):
self.value = 'a'
def my_method(self)
print self.value
class B:
def __init__(self):
self.values = 'b'
def my_method(self, method):
method()
a = A()
b = B()
b.my_method(a.my_method)
Now first this was written just to see how things work. I know I should for example check if my_method 's argument is callable. Now my question is:
How exactly is the method passed here? I mean the output I'm recieving is 'a' so I'm guessing that when a object method is passed as parameter so is the actual object ? In this case when I pass a.my_method the instance a is also passed ?
When you access a.my_method Python sees that it is an attribute of the class and that A.my_method has a method __get__() so it calls A.my_method.__get__(a), that method creates a new object (the 'bound method') which contains both a reference to A.my_method and a reference to a itself. When you call the bound method it passes the call back through to the underlying method.
This happens every time you call any method whether you call it directly or, as in your code, delay the actual call until later. You can find more description of the descriptor protocol as it is known at http://docs.python.org/reference/datamodel.html#descriptors
How exactly is the method passed here?
This is easily answered: in Python, everything is an object :) Also functions/methods, which are specific function objects which can be passed as parameters.
In this case when I pass a.my_method the instance a is also passed?
Yes, in this case the instance a is also passed, though embedded in the function object and cannot be retrieved. On the contrary you could pass the function itself and supply it with an instance. Consider the following example:
b = B()
func = A.my_method # Attention, UPPERCASE A
func(b)
This would call the A classes method my_method with an instance of B.
Functions are 'first-class objects' in Python. What that means is that a function is an object as much as a list or an integer. When you define a function, you are actually binding the function object to the name you use in the def.
Functions can be bound to other names or passed as parameters to functions (or stored in lists, or...).
source: http://mail.python.org/pipermail/tutor/2005-October/042616.html
a.my_method returns not exactly the function you defined in the class A (you can get it via A.my_method) but an object called a 'bound method' which contains both the original function (or 'unbound method' in Python 2, IIRC) and the object from which it was retrieved (the self argument).
I want to send a session object of sqlalchemy to a function of another class .
From class OraDialog's function oraconnect to class oraconn's assign function .
Actually My need is to use the session object in oraconn's another function map
I can't send the session object directly to map function because it is a slot - it is triggered before .
I intended to define the assign function primarily to get the session object.
The Error : ( including print statements )
<sqlalchemy.orm.session.Session object at 0x030808F0>
<sqlalchemy.orm.session.Session object at 0x030808F0>
This is in assign
None
This is in map
Traceback (most recent call last):
File "C:\Users\Arul\Desktop\dbvis\oraconn.py", line 44, in map
for t in self.s.query(tables):
AttributeError: 'NoneType' object has no attribute 'query'
The oraconn class's assign and map functions :
def assign(self,s):
self.s=s
print self.s
print "This is in assign"
def map(self):
print self.s
print "This is in map"
self.table_no=0
for t in self.s.query(tables):
self.table_no=self.table_no+1
table_list.append(t.table_name)
self.item=QtCore.QStringList()
for c in self.s.query(columns):
self.item.append(c.column_name)
self.ui.list_col.addItems(self.item)
SO ,
The assign function receives the object properly . But the map function can't use it - It says Nonetype
My Question :
Two functions of same class can't use an object ?
I must have done something silly - so plz point out......
( I'm using windows7 / python 2.6 / PyQt4 /sqlalchemy /cx_oracle)
Edit :
The calling class :
class OraDialog(QtGui.QDialog):
def __init__(self,parent=None):
QtGui.QDialog.__init__(self,parent)
self.odia=Ui_Dialog()
self.odia.setupUi(self)
self.uiobj=oraconn()
QtCore.QObject.connect(self.odia.but_con,QtCore.SIGNAL('clicked()'),self.uiobj.oraconnect)
def oraconnect(self):
self.setVisible(0)
eng_str="oracle://"+self.odia.line_user.text()+":"+self.odia.line_pass.text()+"#localhost:1521/"+self.odia.line_sid.text()+"?mode="+self.odia.line_role.text()
engine_str=str(eng_str)
engine=create_engine(engine_str)
Session=sessionmaker(engine)
self.s=Session()
print self.s
Problem Solved :
The problem is - i've created two instances and passed from one to another .
Corrected code :
oraconn.assign(myapp,self.s)
where
oraconn -> class
assign -> function of oraconn
myapp -> instance of oraconn , declared for main application
self.s -> the argument i wanted to pass
Thank you Kirk ....
If you're using Qt, then this is likely a GUI app. Maybe there are threading issues; maybe self refers to different objects. It's hard to tell with only what you've given us. Before you go any further, add:
print self
near the top of each method. At least then you can confirm whether both are operating on the same object.
In OraDialog.init, you're saying self.uiobj=oraconn(). Is that the object that's giving you problems? If so: notice that you're creating at as an instance variable, so that each OraDialog object has a different .uiobj object. Could you try making that a class variable by writing:
class OraDialog(QtGui.QDialog):
uiobj = oraconn()
def __init__() [...]
instead? That is, define uiobj as belonging to all instances of the class, not just one instance.
The code you have posted seems to be okay, I can't spot any obvious mistakes.
The problem must be on the calling side. As the self reference can be passed explicitly to methods (via OraDialog.map(my_object), where my_object could be anything) this perfectly possible. Also note that this has nothing to do with scoping.
You should check calling code of the map function. It is very likely it is called on a different object as assign.