Trouble calling methods in Class - python

I'm having trouble calling methods in a class written by someone else (https://github.com/travishathaway/python-ach/blob/master/ach/parser.py). I have done some research but don't fully understand how to call methods with self and other arguments within a class.
The class is written out in the link above, but how do I call any of the methods written out? I have a file in the correct format asked but I cannot get the methods to work. For example, I have tried (and other variations):
a = Parser(file) # where "file" is the filepath
a.__parse_file_header()
This gives me the error: 'Parser' object has no attribute '__parse_file_header'

The methods with 2 underscores in the front are "private" to the class object itself, which is not supposed to be called externally. (Saying that you can still call private methods if you really want to, via mangling)
By the look of the Parser, you should only call as_json or as_dict of the Parser object you initiated with the string variable
eg.
parser = Parser(string_variable)
dict = parser.as_dict()

Related

Define #property on function

In JavaScript, we can do the following to any object or function
const myFn = () => {};
Object.defineProperties(myFn, {
property: {
get: () => console.log('property accessed')
}
});
This will allow for a #property like syntax by defining a getter function for the property property.
myFn.property
// property accessed
Is there anything similar for functions in Python?
I know we can't use property since it's not a new-style class, and assigning a lambda with setattr will not work since it'll be a function.
Basically what I want to achieve is that whenever my_fn.property is to return a new instance of another class on each call.
What I currently have with setattr is this
setattr(my_fn, 'property', OtherClass())
My hopes are to design an API that looks like this my_fn.property.some_other_function().
I would prefer using a function as my_fn and not an instance of a class, even though I realize that it might be easier to implement.
Below is the gist of what I'm trying to achieve
def my_fn():
pass
my_fn = property('property', lambda: OtherClass())
my_fn.property
// will be a new instance of OtherClass on each call
It's not possible to do exactly what you want. The descriptor protocol that powers the property built-in is only invoked when:
The descriptor is defined on a class
The descriptor's name is accessed on an instance of said class
Problem is, the class behind functions defined in Python (aptly named function, exposed directly as types.FunctionType or indirectly by calling type() on any function defined at the Python layer) is a single shared, immutable class, so you can't add descriptors to it (and even if you could, they'd become attributes of every Python level function, not just one particular function).
The closest you can get to what you're attempting would be to define a callable class (defining __call__) that defines the descriptor you're interested in as well. Make a single instance of that class (you can throw away the class itself at this point) and it will behave as you expect. Make __call__ a staticmethod, and you'll avoid changing the signature to boot.
For example, the behavior you want could be achieved with:
class my_fn:
# Note: Using the name "property" for a property has issues if you define
# other properties later in the class; this is just for illustration
#property
def property(self):
return OtherClass()
#staticmethod
def __call__(...whatever args apply; no need for self...):
... function behavior goes here ...
my_fn = my_fn() # Replace class with instance of class that behaves like a function
Now you can call the "function" (really a functor, to use C++ parlance):
my_fn(...)
or access the property, getting a brand new OtherClass each time:
>>> type(my_fn.property) is type(my_fn.property)
True
>>> my_fn.property is my_fn.property
False
No, this isn't what you asked for (you seem set on having a plain function do this for you), but you're asking for a very JavaScript specific thing which doesn't exist in Python.
What you want is not currently possible, because the property would have to be set on the function type to be invoked correctly. And you are not allowed to monkeypatch the function type:
>>> type(my_fn).property = 'anything else'
TypeError: can't set attributes of built-in/extension type 'function'
The solution: use a callable class instead.
Note: What you want may become possible in Python 3.8 if PEP 575 is accepted.

Python: Attribute Error When Passing Method as Function Argument

I was sure that there'd be an answer to this question somewhere on stack overflow, but I haven't been able to find one; most of them are in regards to passing functions, and not methods, as arguments to functions.
I'm currently working with Python 2.7.5 and I'm trying to define a function like this:
def func(object, method):
object.method()
that when called like so:
some_object_instance = SomeObject()
func(some_object_instance, SomeObject.some_object_method)
using a class defined like this:
class SomeObject:
def some_object_method(self):
# do something
is basically equivalent to doing this:
some_object_instance.some_object_method()
I, however, keep getting an attribute error--something along the lines of
'SomeObject' has no attribute 'method'
I was under the impression that I could legally pass methods as arguments and have them evaluate correctly when used in the aforementioned manner. What am I missing?
That's not the way method calling works. The foo.bar syntax looks for a method named bar on the foo object. If you already have the method, just call it:
def func(object, method):
method(object)
func(some_object_instance, SomeObject.some_object_method)
SomeObject.some_object_method is what's called an "unbound method": it's a method object without a self bound into it, so you have to explicitly pass the self to it.
This might make more sense with a concrete example:
>>> s = 'ABC'
>>> s_lower = s.lower # bound method
>>> s_lower()
'abc'
>>> str_lower = str.lower # unbound method
>>> str_lower(s)
'abc'
By comparison, some_object_instance.some_object_method is a "bound method", you can just call it as-is, and some_object_instance is already "bound in" as the self argument:
def func2(method):
method()
func2(some_object_instance.some_object_method)
Unbound methods aren't explained in detail the tutorial; they're covered in the section on bound methods. So you have to go to the reference manual for documentation (in [standard type hierarchy] (https://docs.python.org/2/reference/datamodel.html#the-standard-type-hierarchy), way down in the subsection "User-defined methods"), which can be a little bit daunting for novices.
Personally, I didn't really get this until I learned how it worked under the covers. About a year ago, I wrote a blog post How methods work to try to explain it to someone else (but in Python 3.x terms, which is slightly different); it may help. To really get it, you have to get through the Descriptor HOWTO, which may take a few read-throughs and a lot of playing around in the interactive interpreter before it really clicks, but hopefully you can understand the basic concepts behind methods before getting to that point.
Since you are passing an unbound method to the function, you need to call it as:
method(object)
Or better pass the name of the method as string and then use getattr:
getattr(object, method)()

Using a python class without calling __init__ method?

I am learning python, step-by-step. Today is about Object Oriented Programming. I know how to create and use simple classes, but something bugs me. Most of the objects I use in python do not require to call a constructor
How can this works? Or is the constructor called implicitly? Example:
>>> import xml.etree.ElementTree as etree
>>> tree = etree.parse('examples/feed.xml')
>>> root = tree.getroot()
>>> root
<Element {http://www.w3.org/2005/Atom}feed at cd1eb0>
(from http://www.diveinto.org/python3/xml.html#xml-parse)
I would have gone this way (which actually works):
>>> import xml.etree.ElementTree as etree
>>> tree = etree.ElementTree() # instanciate object
>>> tree.parse('examples/feed.xml')
I'd like to use this way of programming (do not call constructor, or at least call it implicitly) for my own project, but I can't get how it really works.
Thanks
etree.parse is a Factory function. Their purpose is mainly to be convenient ways of constructing objects (instances). As you can easily verify by looking at the source, the parse function does almost exactly as you do in your second example except it ommits a line of code or two.
In this case, what's happening is that the etree.parse() function is creating the ElementTree object for you, and returning it. That's why you don't have to call a constructor yourself; it's wrapped up in the parse function. That function creates an ElementTree instance, parses the data and modifies the new object to correctly represent the parsed information. Then it returns the object, so you can use it (in fact, if you look at the source, it does essentially what you wrote in your second example).
This is a pretty common idiom in object-oriented programming. Broadly speaking, it's called a factory function. Basically, especially for complex objects, a lot of work is required to create a useful instance of the object. So, rather than pack a lot of logic into the object's constructor, it's cleaner to make one or more factory functions to create the object and configure it as needed. This means that someone developing with the library may have several clean, simple ways to instantiate the class, even if "under the hood" that instantiation may be complex.
In the first case, you are calling a helper function from the module. Its not a class method (though internally it might create an object and then call its method). In the second case, you are instantiating an object and then calling its method.
For a class named ClassName, calling ClassName() implicity calls __init__() and returns you a new instance of ClassName.
If __init__ is not defined in ClassName, the super's __init__ will be called.
In your case, this is all inside a function:
def name(foo):
return ClassName(foo)
n = name("bar") # a function call returns a new instance

get fully qualified method name from inspect stack

I have trouble completing the following function:
def fullyQualifiedMethodNameInStack(depth=1):
"""
The function should return <file>_<class>_<method> for the method in the
stack at specified depth.
"""
fileName=inspect.stack()[depth][1]
methodName=inspect.stack()[depth][3]
class= """ please help!!! """
baseName=os.path.splitext( os.path.basename( fileName ) )[0]
return '{0}_{1}_{2}'.format( baseName, className, methodName )
As you can see I want the class name of the method being executed. The stack that inspect returns only has the method name, and I do not know how to find the class belonging to the method.
You are always looking at a function context; the method context is already gone by the time the function executes. Technically speaking, functions act as descriptors when accessed as attributes on an instance (instance.method_name), which return a method object. The method object then, when called, in turn calls the original function with the instance as the first argument. Because this all happens in C code, no trace of the original method object remains on the Python stack.
The stack only needs to keep track of namespaces and the code to be executed for the local namespace. The original function object is no longer needed for these functions, only the attached code object still retains the name of the original function definition for traceback purposes.
If you know the function to be a method, you could search for a self local name. If present, type(self) is the class of the instance, which is not necessarily the class the method was defined on.
You would then have to search the class and it's bases (looping over the .__mro__ attribute) to try and locate what class defined that method.
There are a few more snags you need to take into account:
Naming the first argument of a method self is only a convention. If someone picked a different name, you won't be able to figure that out without parsing the Python source yourself, or by going up another step in the stack and trying to deduce from that line how the function was called, then retrieve the method and it's .im_self attribute.
You only are given the original name of the function, under which it was defined. That is not necessarily the name under which it was invoked. Functions are first-class objects and can be added to classes under different names.
Although a function was passed in self and was defined as part of a class definition, it could have been invoked by manually passing in a value for self instead of the usual route of the method (being the result of the function acting as a descriptor) passing in the self reference for the caller.
In Python 3.3 and up, the situation is marginally better; function objects have a new __qualname__ attribute, which would include the class name. The problem is then that you still need to locate the function object from the parent stack frame.

Converting functions into a methods of a class in python

I'm trying to get the hang of python 2.6, which is my introduction to a programming language. I'm following Learn Python the Hard Way and I must have missed something. I have a set of functions that I want to combine into a class. These functions are contained here. I tried to combine these into a class called "Parsers". This code is contained here.
The functions themselves work outside of the class. I'm trying to call the functions out of the class like this:
import the module:
>>> from ex48 import parser2
Assign the class:
>>> parser_class = parser2.Parsers()
Call a function:
>>> parser_class.parse_subject(word_list, ('noun', 'player'))
I get the following:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ex48/parser2.py", line 60, in parse_subject
verb = parse_verb(word_list)
NameError: global name 'parse_verb' is not defined
Not sure why it's telling me that. Can someone point me in the right direction?
You are confused as to what your code is doing.
This does not assign, a class, it creates an instance, and assigns that instance to a variable:
parser_class = parser2.Parsers()
This calls a method on that instance:
parser_class.parse_subject(word_list, ('noun', 'player'))
The following tells you that there is no global function (or indeed variable of any type) parse_verb:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ex48/parser2.py", line 60, in parse_subject
verb = parse_verb(word_list)
NameError: global name 'parse_verb' is not defined
I expect that you want to change that to verb = self.parse_verb(word_list), which will call the parse_verb method of the same object (self).
There are two problems here, one mechanical, one conceptual. I'll deal with the latter first.
The whole point of a class is that its instances represent some kind of object in your model of the world. For example, a "sentence" is an object, so it makes sense to have a class called Sentence, but a "parsers" is not an object, so Parsers is probably going to be a confused class. Looking at things less abstractly, a class usually has some kind of state, encapsulated in data members that its methods work on.
What you really have here is a parser function that returns a Sentence object (or raises a ParserError). This function could be a method of Sentence, or it could be a free function; it could also be a method of a Parser class if there were any reason for such an object to exist in your model, but there doesn't seem to be one.
If you're just looking to encapsulate all those helper functions so they don't litter the global namespace (a good idea in itself), you don't need to abuse a class to do that. Just make them local functions inside parse_sentence, or put them in a module called parsers.
Now, on to the mechanical problem: If you have a method in a class, you normally only call it through dot syntax: someObject.methodName(params). When a method calls another method of the same object, you use the special self parameter (which you've correctly listed as the first param of each method) to do that. So:
verb = self.parse_verb(word_list)
obj = self.parse_object(word_list)
… and so on for all the other method calls in your sample.
Not every language requires an explicit self like this. For example, in C++ or related languages (Java, C#, etc.), a method can call another method without specifying a target, and it's implicitly assumed that the target is this (the C++ equivalent of self).
It looks like you are working from a python interactive session.
If you've made any changes to parser2.py after importing parser2, then you have to
reload(parser2)
to make those changes known to the interactive interpreter.

Categories