Asked  6 Months ago    Answers:  5   Viewed   23 times

I hope someone can answer this that has a good deep understanding of Python :)

Consider the following code:

>>> class A(object):
...     pass
...
>>> def __repr__(self):
...     return "A"
...
>>> from types import MethodType
>>> a = A()
>>> a
<__main__.A object at 0x00AC6990>
>>> repr(a)
'<__main__.A object at 0x00AC6990>'
>>> setattr(a, "__repr__", MethodType(__repr__, a, a.__class__))
>>> a
<__main__.A object at 0x00AC6990>
>>> repr(a)
'<__main__.A object at 0x00AC6990>'
>>>

Notice how repr(a) does not yield the expected result of "A" ? I want to know why this is the case and if there is a way to achieve this...

I contrast, the following example works however (Maybe because we're not trying to override a special method?):

>>> class A(object):
...     def foo(self):
...             return "foo"
...
>>> def bar(self):
...     return "bar"
...
>>> from types import MethodType
>>> a = A()
>>> a.foo()
'foo'
>>> setattr(a, "foo", MethodType(bar, a, a.__class__))
>>> a.foo()
'bar'
>>>

 Answers

91

Python doesn't call the special methods, those with name surrounded by __ on the instance, but only on the class, apparently to improve performance. So there's no way to override __repr__() directly on an instance and make it work. Instead, you need to do something like so:

class A(object):
    def __repr__(self):
        return self._repr()
    def _repr(self):
        return object.__repr__(self)

Now you can override __repr__() on an instance by substituting _repr().

Tuesday, June 1, 2021
 
vuliad
answered 6 Months ago
80

You can use a decorator to modify the function if you want. However, since it's not a decorator applied at the time of the initial definition of the function, you won't be able to use the @ syntactic sugar to apply it.

>>> class A(object):
...     def test(self):
...         print "orig"
...
>>> first_a = A()
>>> first_a.test()
orig
>>> def decorated_test(fn):
...     def new_test(*args, **kwargs):
...         fn(*args, **kwargs)
...         print "new"
...     return new_test
...
>>> A.test = decorated_test(A.test)
>>> new_a = A()
>>> new_a.test()
orig
new
>>> first_a.test()
orig
new

Do note that it will modify the method for existing instances as well.

EDIT: modified the args list for the decorator to the better version using args and kwargs

Wednesday, July 28, 2021
 
Rudie
answered 4 Months ago
76

Here's an example of dynamically creating module objects using the imp module

Sunday, August 1, 2021
 
JakeGR
answered 4 Months ago
89

You've got 1 2 1 in some magic section, because private methods are resolved w/o polymorphism, compiler creates call to method contained in type variable declared with, in your case Test3. Declare print1 as non-private in Test3 (and, consequently, in Test4 as it's prohibited to tighten access modifiers of methods) and see polymorphism in action, so you'll get expected 1 2 2.


Consider shorter example:

class Test {

    private static class Test3 {
        private void print1() {
            System.out.println("non-polymorphic 1");
        }

        void polymorphic() {
            System.out.println("polymorphic 1");
        }
    }

    private static class Test4 extends Test3 {
        private void print1() {
            System.out.println("non-polymorphic 2");
        }

        void polymorphic() {
            System.out.println("polymorphic 2");
        }
    }

    public static void main(String[] args) {
        Test4 t4 = new Test4();
        t4.print1();
        t4.polymorphic();

        System.out.println("======");

        Test3 t34 = new Test4();
        t34.print1();
        t34.polymorphic();
    }
}

CLARIFICATION ... to my comment to this answer: polymorphism isn't effective for access to data fields, only for methods. Consider:

private static class Test3 {
    int i = 1;
}

private static class Test4 extends Test3 {
    int i = 2;
}

public static void main(String[] args) {
    Test4 t4 = new Test4();
    System.out.println(t4.i);

    System.out.println("======");

    Test3 t34 = new Test4();
    System.out.println(t34.i);
}

Despite i declared non-private, t34.i value is 1.

Saturday, August 21, 2021
 
Shoarc
answered 4 Months ago
50

You don't need to declare execute() in the Binary class since it's already inherited from Command. Abstract methods don't need to be implemented by other abstract classes - the requirement is passed on to the eventual concrete classes.

public abstract class Command
{
    public abstract object execute();
}

public abstract class Binary : Command
{
    //the execute object is inherited from the command class.
}

public class Multiply : Binary
{
    public override object execute()
    {
        //do stuff
    }
}
Tuesday, September 21, 2021
 
tiny
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share