【Pyhont笔记】__new__和__init__

一、先理解cls和self

此部分原文:python中self和cls的区别_python self()当成一个函数-CSDN博客

假如你有个类MyClass,其中有个fun(arg1,arg2),以及一个实例obj,

当你应用中要通过实例类的方法,创建函数时必须加self参数,因为,当你调用方法obj.fun(arg1,arg2)的时候,会自动转成MyClass.fun(obj,arg1,arg2)

当你直接通过类调用方法时,可以不用sefl参数,如直接MyClass.fun(arg1,arg2),需加@staticmethod 修饰,否则会报错

若不想修饰,则建个module.py文件,不建类,则可直接如下方法使用:

import module

mudule.fun(arg1,arg2)

1、self表示一个具体的实例本身。如果用了staticmethod,那么就可以无视这个self,将这个方法当成一个普通的函数使用。

2、cls表示这个类本身

>>> class A(object):
        def foo1(self):
            print "Hello",self
        @staticmethod
        def foo2():
            print "hello"
        @classmethod
        def foo3(cls):
            print "hello",cls


>>> a = A()

>>> a.foo1()          #最常见的调用方式,但与下面的方式相同
Hello <__main__.A object at 0x9f6abec>

>>> A.foo1(a)         #这里传入实例a,相当于普通方法的self
Hello <__main__.A object at 0x9f6abec>

>>> A.foo2()          #这里,由于静态方法没有参数,故可以不传东西
hello

>>> A.foo3()          #这里,由于是类方法,因此,它的第一个参数为类本身。
hello <class '__main__.A'>

>>> A                 #可以看到,直接输入A,与上面那种调用返回同样的信息。
<class '__main__.A'>

3、whats more,类先调用__new__方法,返回该类的实例对象,这个实例对象就是__init__方法的第一个参数self,即self是__new__的返回值。

二、再理解__new__和__init__

参考1:https://juejin.im/post/5add4446f265da0b8d4186af

参考2:https://zhuanlan.zhihu.com/p/21379984

__init__ 方法为初始化方法, __new__方法才是真正的构造函数

__new__方法用于创建对象并返回对象,当返回对象时会自动调用__init__方法进行初始化

调用过程,先__new__ 再 __init__

# coding:utf-8


class Foo(object):
    '''黄哥python培训,黄哥所写'''
    price = 50

    def how_much_of_book(self, n):
        print(self)
        return self.price * n

foo = Foo()
print(foo.how_much_of_book(8))
print(dir(Foo))

分析上面的代码,这个类实例化过程,Foo类继承object类,继承了object的__new__方法

当你没有重写这个方法(通俗来说,你没有在Foo类中没有定义__new__方法),Foo实例化是默认自动调用父类__new__方法,这个方法返回值为类的实例提供这个函数how_much_of_book,默认的第一个参数self。

本质上,__new__ 中可以实现 __init__ 中的所有逻辑,但反过来不行。__init__通常更关注业务逻辑的初始化。

 单例模式的实现:

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kwargs)
            #或 cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)

        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(s1)
print(s2) 

上面的代码输出

<__main__.Singleton object at 0x7fdef58b1190>
<__main__.Singleton object at 0x7fdef58b1190>

可以看到s1和s2都指向同一个对象,实现了单例模式

工厂模式的实现

class Fruit(object):
    def __init__(self):
        pass

    def print_color(self):
        pass

class Apple(Fruit):
    def __init__(self):
        pass

    def print_color(self):
        print("apple is in red")

class Orange(Fruit):
    def __init__(self):
        pass

    def print_color(self):
        print("orange is in orange")

class FruitFactory(object):
    fruits = {"apple": Apple, "orange": Orange}

    def __new__(cls, name):
        if name in cls.fruits.keys():
            return cls.fruits[name]()
        else:
            return Fruit()

fruit1 = FruitFactory("apple")
fruit2 = FruitFactory("orange")
fruit1.print_color()    
fruit2.print_color()    

上面的代码输出

apple is in red
orange is in orange

cls可以传参数的:

class PriceLog(object):
    def __init__(self, timestamp, product_id, price):
        self.timestamp = timestamp
        self.product_id = product_id
        self.price = price
    def __repr__(self):
        return '<PriceLog ({}, {}, {})>'.format(self.timestamp,self.product_id, self.price)
    @classmethod
    def parse(cls, text_log):
        '''
         Parse from a text log with the format
            [<Timestamp>] - SALE - PRODUCT: <product id> - PRICE: $<price>
         to a PriceLog object
        '''
        divide_it = text_log.split(' - ')
        tmp_string, _, product_string, price_string = divide_it
        timestamp = delorean.parse(tmp_string.strip('[]'))
        product_id = int(product_string.split(':')[-1])
        price = Decimal(price_string.split('$')[-1])
        return cls(timestamp=timestamp, product_id=product_id,price=price)
    

So, the parsing can be done as follows:
>>> log = '[2018-05-05T12:58:59.998903] - SALE - PRODUCT: 897 - PRICE:
$17.99'
>>> PriceLog.parse(log)
<PriceLog (Delorean(datetime=datetime.datetime(2018, 5, 5, 12, 58, 59,
998903), timezone='UTC'), 897, 17.99)>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值