Python Polymorphism How do you redefine a function inside a method

Suppose we have the following code. I want to change the internal function parse_place . How do you do this without replacing the whole method?

 class GoogleV3Place(GoogleV3): """Simply extends the GoogleV3 to bucket the object into a place""" def parse_json(self, page, exactly_one=True): """Returns location, (latitude, longitude) from json feed.""" if not isinstance(page, basestring): page = util.decode_page(page) self.doc = json.loads(page) places = self.doc.get('results', []) if not places: check_status(self.doc.get('status')) return None elif exactly_one and len(places) != 1: raise ValueError( "Didn't find exactly one placemark! (Found %d)" % len(places)) def parse_place(place): """This returns an object how we want it returned.""" location.formatted_address = place.get('formatted_address') location.latitude = place['geometry']['location']['lat'] location.longitude = place['geometry']['location']['lng'] latitude = place['geometry']['location']['lat'] longitude = place['geometry']['location']['lng'] return (location, (latitude, longitude)) if exactly_one: return parse_place(places[0]) else: return [parse_place(place) for place in places] 
+4
source share
4 answers

If you have control over the GoogleV3Place code (i.e. the code you wrote and which is not in the library), I would refactor parse_json to accept the parse_place_fn argument and move parse_place to the top- (if accessibility is a problem, you can always prefix it double underlined):

 def parse_place(place): """This returns an object how we want it returned.""" location.formatted_address = place.get('formatted_address') location.latitude = place['geometry']['location']['lat'] location.longitude = place['geometry']['location']['lng'] latitude = place['geometry']['location']['lat'] longitude = place['geometry']['location']['lng'] return (location, (latitude, longitude)) class GoogleV3Place(GoogleV3): """Simply extends the GoogleV3 to bucket the object into a place""" def parse_json(self, page, exactly_one=True, parse_place_fn = parse_place): """Returns location, (latitude, longitude) from json feed.""" if not isinstance(page, basestring): page = util.decode_page(page) self.doc = json.loads(page) places = self.doc.get('results', []) if not places: check_status(self.doc.get('status')) return None elif exactly_one and len(places) != 1: raise ValueError( "Didn't find exactly one placemark! (Found %d)" % len(places)) if exactly_one: return parse_place_fn(places[0]) else: return [parse_place_fn(place) for place in places] 

Now, any function that you create that takes up space and returns a tuple of the form (location, (latitude, latitude)) can be passed to parse_json, and if no function is specified, it uses the default parse_place value.

+3
source

The correct way to do this is at compile time. You need to create an abstract base class (ABC) with the abc module. This will not allow client code to instantiate the class if virtual functions that are caught at compile time are not implemented. Good for polymorphic programming. Virtual functions are those that have the @abstractmethod decorator. You can also define real functions in the ABS.

 import abc class MyABC(object): __metaclass__ ABCMeta @abstractmethod def my_virtual_function(self): pass def real_function(self): print "ABClass function" 

The resulting class now inherits ABC and implements virtual functions.

 class MyDerived(MyABC): def my_virtual_function(self): print "ok" 

For this, you must have python 2.6 or later.

More on the topic ... http://docs.python.org/library/abc.html

if you are stuck with python 2.4 then you have to deal with a much less desirable situation. You must have a base class that throws an exception at runtime.

 class MyBaseClass(object): def my_redefinable(self): raise NotImplementedError("You must implement my_redefinable() ") class MyDerivedClass(MyBaseClass): def __init__(self): pass def my_redefinable(self): print "ok" test = MyBaseClass() test.my_redifinable() # throws error test = MyDerivedclass() test my_redefinable() # is ok 
+1
source

If you really want to make a method polymorphic, you can use called objects instead of functions. You can delegate a call to a private class of the class or implement binding to instances in called objects.

But in this particular example there is no reason to embed parse_place in parse_json

0
source

You cannot access nested functions, they are visible only inside the function, for example, local variables. However, you can put parse_place in a separate method and then override with regular inheritance.

0
source

Source: https://habr.com/ru/post/1398259/


All Articles