[Tutor] How to know the internal execution flow of class
Deepak Dixit
deepakdixit0001 at gmail.com
Sun Feb 16 05:17:38 EST 2020
Thanks Mats, I am agree with *Tim Peters *statement but I don't want to be
one who know to write programs only. I am curious to know the internals of
python :)
BTW, Thanks for your well explanation, it helps me a lot to understand,
specially __call__. Is there anything happening also when we are defining a
*function* like the class ? One question regarding type, see this script-
# Python 2.7.16 on Linux
>>> type(dict)
<type 'type'>
>>> type(type)
<type 'type'>
>>> type(object)
<type 'type'>
>>>
Here I am getting *type(type) = <type 'type'> * which confuses me. Is there
any relation between 'type' and base/parent class of any object? what is
the benefit of 'type' for a programmer?
On Sat, Feb 15, 2020 at 11:21 PM Mats Wichmann <mats at wichmann.us> wrote:
> On 2/15/20 8:08 AM, Deepak Dixit wrote:
> > Hi Tutors,
> >
> > What happens when we create a class or function. In other way, I want to
> > know the life-cycle of class. Lets see an example:
> >
> > ######### Script Start #########
> >
> > class MClass(type):
> > def __new__(cls, *args):
> > print 'New from MClass', args[0]
> > return super(MClass, cls).__new__(cls, *args)
> >
> > class A:
> > print 'Class A defined'
> > __metaclass__ = MClass
> >
> > def __init__(self, *args):
> > print 'Init from A', args
> >
> > def __new__(cls, *args):
> > print 'New from A', args
> > return super(A, cls).__new__(cls, *args)
> >
> > print 'Class A definition end'
> > a = A()
> > print 'Object created: A'
> >
> > class B:
> > print 'Class B defined'
> > __metaclass__ = MClass
> >
> > def __init__(self, *args):
> > print 'Init from B', args
> >
> > def __new__(cls, *args):
> > print 'New from B', args
> >
> > print 'Class B definition end'
> > b = B()
> > print 'Object created: B'
> >
> > ######### Script End #########
> >
> > ################# Output ############
> > Class A defined
> > New from MClass A
> > Class A definition end
> > New from A ()
> > Init from A ()
> > Object created: A
> > Class B defined
> > New from MClass B
> > Class B definition end
> > New from B ()
> > Object created: B
> >
> > ################# Output End ############
> > From this example , we can see that when we are defining any class ( not
> > creating object), it call some methods from the metaclass. If I am
> > returning something from __new__ then it call __init__ of current class
> > otherwise it skips the calling even when I am creating object. Now
> suppose
> > that If I never assigned any metaclass manually then I will not be aware
> > that something is happening when I am defining the class.
> >
> > How can I know these internals?
>
> First off here's a moderately famous quote from one of the most famous
> Python developers:
>
> “Metaclasses are deeper magic than 99% of users should ever worry
> about. If you wonder whether you need them, you don’t (the people who
> actually need them know with certainty that they need them, and don’t
> need an explanation about why).”
>
> — Tim Peters
>
> Ignoring any niggles about Python 2 and old-style classes, if you don't
> define a metaclass, your class has one anyway: it's "type". So this same
> flow happens for every class statement. Every callable object has a
> special method __call__ which is invoked when you "call" that object, a
> metaclass is no different. A metaclass is a template for creating a
> class similar to how a class is a template for creating an object - you
> call it and you get the object back. Thus when you create class A or B,
> the metaclass is called - by invoking __call__, which invokes the
> __new__ and __init__ methods, and you see your message from the
> metaclass's init. It you don't provide a metaclass (which inherits from
> type), or don't provide those methods, then the ones from type are
> called as with any inheritance relationship. Since you can't muck with
> type for safety reasons, inserting a custom metaclass is useful for
> experimentation, as you've done. For the rest, see Tim's quote :)
>
> Seriously, did that clear any of the confusion up?
>
> Btw. the more preferred form now is:
>
> class A(metaclass=MClass):
> print 'Class A defined'
>
> as opposed to defining __metaclass__
>
>
> P.S. - stuff you didn't ask for:
>
> You can create a class by calling type directly, by the way; the magic
> of the class statement is you don't have to do that, since it
> automatically calls type (or any metaclass you supply). Here's
> something I had sitting around from a tutorial I did for someone. Maybe
> it will amplify a little more? Here are the pieces of what we think of
> as a Python class:
>
> # some methods
> def transact(acct, amount):
> acct.balance += amount
>
> def pay_interest(acct):
> acct.balance += acct.balance * acct.interest_rate
>
> def account_init(acct, num, name, bal, rate):
> acct.acct_number = num
> acct.acct_holder = name
> acct.balance = bal
> acct.interest_rate = rate
>
> # a mapping for methods and attributes:
> account = {
> "acct_number": "",
> "acct_holder": "",
> "balance": 0.0,
> "interest_rate": 0.0,
> "transact": transact,
> "pay_interest": pay_interest,
> "__init__": account_init,
> }
>
> # and create it with name, parents (none), mapping:
> AccountType = type("AccountType", (), account)
>
>
> # that gives the same result as this:
> class AccountType():
> def transact(self, amount):
> self.balance += amount
>
> def pay_interest(self):
> self.balance += self.balance * self.interest_rate
>
> def __init__(self, num, name, bal, rate):
> self.acct_number = num
> self.acct_holder = name
> self.balance = bal
> self.interest_rate = rate
>
> # you can call either AccountType to create an instance - they're the
> same thing!
> _______________________________________________
> Tutor maillist - Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>
--
*With Regards,*
*Deepak Kumar Dixit*
More information about the Tutor
mailing list