【python类】类

1. 类的命名空间

1> 简单变量和属性名称
    1. 简单变量名(无点号):遵循函数LEGB做用域法则
         ==> 赋值(X = value):// 使变量成为本地变量:除非声明是全局的
         ==> 引用(X):// LEGB搜索变量
     2. 属性名称(点号属性名称):遵循模块和类的规则
         ==> 赋值(object.X = value)  // 实例对象命名空间内建立、修改变量
         ==> 引用(object.X):// 基于类的对象:对象内遵循继承搜索;模块:对象中直接读取X(模块中存在类对象,模块没有继承的概念)
    2> 命名空间组成:命名空间字典和命名空间连接
        属性点号运算实际是内部字典的取值; // x.data = x.__dict__['data']

        x.__dict__  // 获取实例的命名空间
        x.__class__  // 获取实例的父类
        sub.__bases__  //  sub类的父类

        命名空间连接:当前命名空间找不到,会按照继承搜索查找
        """
        父类层次:
        B: B --> A
        F: F --> D --> B --> A --> C --> A --E 
        """
        class A: pass
        class B(A): pass
        class C(A): pass
        class D(B,C): pass
        class E: pass
        class F(D,E): pass

2. 继承

*继承原理:实际也是继承树的应用,子类实例老是先去查找本身的命名空间,而后才去查找父类命名空间*
    class Manager(Person):
   # 7 调用父类的构造函数:咱们能够决定哪些参数使用父类,好比此处的Job
             def __init__(self,name,pay):
                     Person.__init__(self,name,'mgr',pay)
             def givePay(self,percent,bouns=.10):
       # 调用方法两种方式 1) 实例.方法() 2)类.方法(self) 无论哪一种,方法都须要传递一个self调用
                     Person.givePay(self,percent + bouns)
   # 6.2 继承:扩展子类行为,只能在子类实例对象使用
             def doSomething(self):
                         return '[%s %s]' %(self.__class__.__name__,"考核")

    """
        # coding:utf-8
        """
        类的继承
        """

        class Employees:
            def __init__(self,name,salary=0):
                    self.name = name
                    self.salary = salary
            def givePay(self,percent):
                    self.salary = self.salary + (self.salary * percent)
            def work(self):
                    print(self.name,"does stuff")
            def __repr__(self):
                    return "<Employees: name:%s,salary:%s>" %(self.name,self.salary)

        class Chef(Employees):
            def __init__(self,name):
                    Employees.__init__(self,name,50000)
            def work(self):
                    print(self.name,'make foods')

        class Server(Employees):
            def __init__(self,name):
                    Employees.__init__(self,name,40000)
            def work(self):
                    print(self.name,'interfaces to customer')

        class PizzaRobbt(Chef):
                def __init__(self,name):
                        Chef.__init__(self,name)
                def work(self):
                        print(self.name,'make pizza')

        if __name__ == "__main__":
        # 必定要分清楚:object.attr 和 赋值
        # 继承是从点号运算开始的,触发实例、类以及超类中属性搜索
                bob = PizzaRobbt('bob')
                print(bob)
                bob.work()
                bob.givePay(0.2)
                print(bob)

            for kclass in Employees,Chef,Server,PizzaRobbt:
            # kclass.__name__ 是一个字符串
                    obj = kclass(kclass.__name__)
                        obj.work()
            """

            """

            """
                类的组合:order下单包含Server、Customer、PizzaRobbt一块儿完成一件事情.
            """

            from employees import Server,PizzaRobbt

            class Customer:
                    def __init__(self,name):
                            self.name = name
                    def order(self,server):
                            print(self.name,"order pizza",server)
                    def pay(self,server):
                            print(self.name,'pay money',server)

            class Oven:
                    def bake(self):
                            print('ovens bakes')

            class PizzaShop:
                    def __init__(self):
                            self.server = Server('Pat')
                            self.chef = PizzaRobbt('bob')
                            self.oven = Oven()
                    def order(self,name):
                            customer = Customer(name)
                            customer.order(self.server)
                            self.chef.work()
                            self.oven.bake()
                            customer.pay(self.server)

                if __name__ == "__main__":
                        scene = PizzaShop()
                        scene.order('tom')

             """

3. 抽象超类

*父类中的方法具体在子类中实现;抽象超类是不能被继承的,除非全部抽象方法都在子类实现*
    """
    class Super:
             def method(self):
                     print("in Super.method")
             def delegate(self):
                     self.action()
       # 要是子类没有提供action,那么就会抛错:采用assert
       # assert False,'action must be method!'

     class Provider(Super):
             def method(self):
                    print('starting Sub.method')
                    Super.method(self)  // 扩展父类的方法
                    print('ending Sub.method')
             def action(self):  // 实现父类的抽象方法
                    print('In Provider.action')
    """

4. 运算符重载

# coding:utf-8

        """
            运算符重载
        """
        import operator

        class Number:
        # 1. 拦截构造方法
                def __init__(self,data):
                        self.data = data
        # 2. 拦截减法运算
                def __sub__(self, other):
                        return Number(self.data - other)

        class Indexer:
                def __init__(self,data):
                        self.data = data
                # 3.1 拦截索引、切片操做:实例对象拥有索引、切片操做
                # 3.1 重载迭代:每次迭代实例对象时都会调用该方法,传入索引值
                def __getitem__(self, item):
                        print('getitem:',item)
                        return self.data[item]
                # 3.2 拦截索引赋值、切片赋值操做:实例对象拥有索引赋值、切片赋值操做
                def __setitem__(self, key, value):
                        self.data[key] = value

        class Squeres:
        """
  iter() 迭代器工厂函数
            __iter__() 迭代器协议,能够在自定义类里面造成迭代器 调用方式 1:手动next(i)调用    2:可迭代环境调用

     可迭代对象:能够用迭代环境循环的对象
    迭代器:支持迭代协议(也就是可使用next调用);迭代器是能够记住状态的

    可迭代对象不必定是迭代器 (for i in 'spam':)
    迭代器必定是可迭代对象(支持在迭代环境循环调用)
"""
                def __init__(self,start,stop):
                        self.value = start - 1
                        self.stop = stop
                # 3.3 在任何迭代环境中,会优先调用__iter__;以后调用__getitem__
                # __iter__调用迭代协议;__getitem__调用索引取值,知道抛出索引超范
                # __iter__ 根本没有重载索引表达式:X = Squeres(1,5) X[1] 报错
                # __iter__ 只循环一次: X = Squeres(1,5) [for i in X] ==> 第二次迭代会为空
                def __iter__(self):  # 定义了__iter__的方法,类实例是可迭代对象
                        return self  # 此处返回self,每次生成的可迭代对象只能调用一次
                def __next__(self):
                        if self.value == self.stop:
                                raise StopIteration
                        self.value += 1
                        return self.value

            # 调用next方法
            class SkipIterator:
                    def __init__(self,wrapper):
                            self.wrapper = wrapper
                            self.offset = 0
                    def __next__(self):
                            if self.offset >= len(self.wrapper):
                                    raise StopIteration
                            item = self.wrapper[self.offset]
                            self.offset += 2
                            return item

                # 返回迭代器对象
                class SkipObject:
                        def __init__(self,wrapper):
                                    self.wrapper = wrapper
                        def __iter__(self):
                                    return SkipIterator(self.wrapper)

            class Iter1:
            """
    1. 成员关系:contains(映射) --> iter --> getitem
    2. __iter__和__getitem__ 均可捕获迭代环境
      区别:1 __iter__ 使用迭代协议获取值(__next__),且能够保持状态信息;__getitem__ 使用索引获取值
           2 __getitem__ 能够支持索引和切片操做
           3 当字段索引行数据时(list、tuple),二者可替换;为hash类型时(dict、set),只能用__iter__
"""
                        def __init__(self,value):
                                    self.value = value
                        def __getitem__(self, item):
                                    print("getitem:",item)
                                    return self.value[item]
                        def __iter__(self):
                                    print("iter=>",end="")
                                    self.offset = 0
                                    return self
                        def __next__(self):
                                    print("next:",end="")
                                    if self.offset == len(self.value):
                                            raise StopIteration
                                    item = self.value[self.offset]
                                    self.offset += 1
                                    return item
                    def __contains__(self, item):
                                    print("contanins: ",end='')
                                    return item in self.value

        class Library(object):
                    def __init__(self):
                                self.books = {'title': 'a', 'title2': 'b', 'title3': 'c', }

                    def __getitem__(self, i):
                                return self.books[i]

                    def __iter__(self):
                            # 方法1 使用生成器
                            for titles in self.books:
                                    yield self.books[titles]

        class Empty:
            """
    拦截属性点号操做;
    若是python能够在继承树(self.__dict__)找到该属性,那么__getattr__方法不会被调用

    赋值:self.attr = value ==> self.__setattr__(attr,value)
        """
                    def __init__(self):
                            self.data = 0
                    def __getattr__(self, item):
                            if item == "age":
                                    print("__getattr__:",item,end=" ")
                                    return 40
                            else:
                                    raise AttributeError(item)
                    def __setattr__(self, key, value):
                            if key == "data":
                            # 此处必定用self.__dict__[key] = value
                            # 所以在__setattr__里面赋值,会再调用__setattr__,形成内存溢出
                                        self.__dict__[key] = value
                            else:
                                        raise AttributeError(key + "not allowed")

            class A:
            """
    1.
    __add__ 原处加法(a + b ;a += 1)
    __radd__ 右侧加法
    2.
    a + b ,python会先去a里面找__add__,找不到会去__radd__查找
    这个例子: b + a 会报错,由于python会先去B找__add__,而后去A找__radd__,均不知足
    3. 每一个二元运算符都支持:包括 __sub__(减法)
"""
                        def __init__(self,val):
                                    self.val = val
                        def __add__(self, other):
                                    return self.val + other
            class B:
                        def __init__(self,val):
                                    self.val = val
                        def __radd__(self, other):
                                    return self.val + other

            class Callee:
                """
    编写api接口经常使用:能够将类和实例调用看成函数来使用,而且能够将实例的状态保留到函数内部,天然而然成为了被一个函数记住
    ==>并调用另外一个函数的实现
    __call__ 任何定义了该方法的类和实例 支持与常规函数一致的调用

    c = Callee()
    c(1,2,3) ==> __call__ (1,2,3) {}
"""
                def __call__(self, *args, **kwargs):
                            print("__call__,",args,kwargs)

        class CallBack:
                    def __init__(self,color):
                            self.color = color
                    def __call__(self):
                            print('turn',self.color)

    class BiJiao:
"""
比较:__lt__ __gt__ __cmp__(python3.0失效,使用operator替代)
"""
            pass

    class Bool1:
"""
    拦截布尔操做
    __bool__ >> __len__
    python 3.0 优先尝试__bool__ python 2.6优先尝试__len__
"""
                def __bool__(self):
                            return True
相关文章
相关标签/搜索