码迷,mamicode.com
首页 > 编程语言 > 详细

【python类】类

时间:2018-12-03 01:10:12      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:协议   二次   抽象   关系   *args   offset   加法   starting   __add__   

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

【python类】类

标签:协议   二次   抽象   关系   *args   offset   加法   starting   __add__   

原文地址:http://blog.51cto.com/kongxiaofa/2325065

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!