zoukankan      html  css  js  c++  java
  • 面向对象简介(看书)

    一、变量介绍

    mo = 8
    class Foo():
        YY = 5
        def __init__(self,x):
            self.age=2       #实例变量,Java中的public
            self.__priv=8   #私有变量,Java中的private
            a = 1              #局部变量
            Foo.YY = 3      #类变量,所有实例共享。
            mo = 9           #全局变量

    二、多态、继承、聚集

    '''
    多态:
    子类和父类中有相同的方法,将调用子类的方法,super()将调用父类的方法
    
    继承----is a关系
    继承的作用是进行代码的重用
    继承里面遇到有重写的方法最好是每个方法之前都调用父类的方法。
    因为这样会使继承变得有意义例如__init__()
    最好的执行顺序是先执行父类的构造方法,再执行子类的构造方法
    如果没有重写,调用子类的方法将直接调用父类的方法
    
    聚集----某类里包含别的类对象has a关系
    '''

    三、经典类,新式类

    #经典类:没有指定基类,所以是object的子类
    class className:
        suite
    #新式类:
    class className(base_classes):
        suite

    四、hash

    '''
    所有自定义对象都是可以hash的,(可以作为字典的键),
    都可以进行hash运算。如果重新实现了__eq__()就不可hash了
    '''

    五、Point类

    '''
    Shape.py
    实例变量:self.x和self.y
    实例变量可以通过对象直接访问,不是私有的。私有变量应该是__x和__y这种
    私有方法是def __func(self): pass这种。也是不能直接通过对象访问的,只能在类里面使用
    self表示本对象自己。
    创建一个对象有两个步骤:
    1、调用__new__()创建该对象
    2、调用__init__()对其进行初始化
    这里是object.__new__()然后point.__init__()
    在实际编程中,我们只需要重新实现__init__()方法,new方法使用object.__new__()已经足够
    某种编码风格--在自定义__init__()的起始处总是调用super().__init__()是一种合理的做法。
    直接继承自object的类,没有必要这样处理。一般只在必须的时候才调用基类的方法
    '''
    class Point:
        def __init__(self, x=0, y=0):
            self.x = x
            self.y = y
        def distance_from_origin(self):
            return (self.x ** 2 + self.y ** 2) ** 0.5
        def __eq__(self, other):
            if not isinstance(other,Point):
                return NotImplemented   #将调用other.__eq__(self)如果没有实现或也返回NotImplement将抛出TypeError错误
            return self.x==other.x and self.y==other.y
        def __repr__(self):
            return "Point({0.x},{0.y})".format(self)
        def __str__(self):
            return "({0.x},{0.y})".format(self)
    
    a = Point()
    print(repr(a))  # Point(0,0)
    b = Point(3,4)
    print(str(b))   # (3,4)
    print(b.distance_from_origin())  # 5.0
    b.x = -19
    print(str(b))   # (-19,4)
    print(a==b,a!=b) # False True
    print(a == int(4)) # False
    
    '''
    test.py
    '''
    import Shape
    p = Shape.Point(3,4)
    print(repr(p))   # Point(3,4)
    q = eval(p.__module__+"."+repr(p))
    print(p.__module__)  # Shape
    s = "Shape.Point(3,4)"
    s1 = eval(s)
    print(q.x, s1.x)  # 3 3
    Point类

    六、Circle类

    '''
    1、通过super()调用基类的方法
    2、在super()调用中不需要传递self参数,因为Python会自动传递这一参数
    3、多态,Circle对象在使用时都可以当成Point对象来使
    4、@property:方法返回float,可以吧方法当做只读的属性使用
    5、property修饰器函数有四个参数(获取者函数,设置者函数,删除者函数,docstring)
       类似fset(func.__name__,func())
    '''
    from Shape import Point
    class Circle(Point):
        def __init__(self, radius, x=0, y=0):
            super().__init__(x, y)
            self.radius = radius
        def edge_distance_from_origin(self):  #圆边缘到圆心的距离
            return abs(self.edge_distance_from_origin() - self.radius)
        @property
        def area(self):
            return 3.14 * self.radius ** 2
        def circumference(self):
            return 2 * 3.14 * self.radius
        def __eq__(self, other):
            return self.radius == other.radius and super().__eq__(other)
        def __repr__(self):
            return "Circle({0.radius},{0.x},{0.y})".format(self)
        def __str__(self):
            return repr(self)
    
    p = Point(3,4)
    c = Circle(2,3,4)
    print(p.distance_from_origin())   # 5.0
    print(c.distance_from_origin())   # 5.0
    print(c.area)    # 12.56
    ####################################################################################################################
    '''
    将radius属性变为特性实现:
        初始化时radius也不能为负数
        赋值时,radius也不能为负数
    使用@property创建radius特性后,
    radius.setter  radius.getter  radius.deleter都可用
    assert: 相当于raise-if-not
    '''
    class C:
        def __init__(self, radius):
            self.__radius = radius
        @property
        def radius(self):
            '''以下是docstring:
            >>> c=C(-2)
            AssertionError:radius must be nonzero and non-negative
            '''
            return self.__radius
        @radius.setter
        def radius(self, radius):
            assert radius > 0, "radius must be nonzero and non-negative"
            self.__radius = radius
    
    
    c = C(8)
    print(c.radius)   # 8
    c.radius = -3     # 报错"radius must be nonzero and non-negative"
    print(c.radius)
    Cycle继承Point

    七、FuzzBool继承object

    '''
    说明
    1、在Python中del函数是删除对象的一个引用,只有当对象的引用为0时才执行__del__()方法
    2、Python中一般不使用静态方法,而是使用模块函数或者类方法
    
    FuzzBool类
    1、支持(==、!=、>、>=、<、<=)比较操作符
    2、支持逻辑操作符not(~)、and(&)、or(|)、&=、|=
    3、两种其他逻辑方法conjunction()、disjunction()
    4、bool、int、float、str数据类型转换功能
    5、可使用eval()评估的表象形式
    6、str.format()格式规约支持
    7、可作为字典的键(支持hash)
    '''
    
    class FuzzBool:
        def __init__(self, value=0.0):
            self.__value = value if 1.0 >= value >= 0.0 else 0.0
        # (==、!=、>、>=、<、<=)比较操作符
        def __eq__(self, other):
            return self.__value == other.__value
        def __ne__(self, other):
            return self.__value != other.__value
        def __gt__(self, other):
            return self.__value > other.__value
        def __ge__(self, other):
            return self.__value >= other.__value
        def __lt__(self, other):
            return self.__value < other.__value
        def __le__(self, other):
            return self.__value <= other.__value
        # not(~)、and(&)、or(|)、&=、|=
        def __invert__(self):
            return FuzzBool(1.0 - self.__value)
        def __and__(self, other):
            return FuzzBool(min(self.__value, other.__value))
        def __iand__(self, other):
            self.__value = min(self.__value, other.__value)
            return self
        def __or__(self, other):
            return FuzzBool(max(self.__value, other.__value))
        def __ior__(self, other):
            self.__value = max(self.__value, other.__value)
            return self
        # 可使用eval()评估的表象形式
        def __repr__(self):
            return "{0}({1})".format(self.__class__.__name__, self.__value)
        # bool、int、float、str数据类型转换
        def __bool__(self):
            return self.__value > 0.5
        def __int__(self):
            return round(self.__value)
        def __float__(self):
            return self.__value
        def __str__(self):
            return str(self.__value)
        # 可作为字典的键(支持hash)
        def __hash__(self):
            return hash(id(self))
        # 格式规约支持
        def __format__(self, format_spec):
            return self.__value.__format__(format_spec)
        # 两种其他逻辑方法conjunction()、disjunction()
        @staticmethod
        def conjunction(*fuzzies):
            return FuzzBool(min([float(f) for f in fuzzies]))
    
        @staticmethod
        def disjunction(*fuzzies):
            return FuzzBool(max([float(f) for f in fuzzies]))
    f1 = FuzzBool(0.2)
    f2 = FuzzBool(0.50001)
    f1 |= f2
    print(f1 )
    fx = eval("FuzzBool(0.3)")
    print(bool(f2))
    print(hash(f2))
    print("{0}".format(f1))
    FuzzBool继承object

    八、FuzzBool继承float

    '''
    __new__()是一个类方法,但不需要用@classmethod特别指明
    类方法的第一个参数是由Python指定的,也就是方法所属的类
    '''
    class FuzzBool(float):
        def __new__(cls, value):
            return super().__new__(cls, value if 1.0 >= value >= 0.0 else 0.0)
        def __invert__(self):
            return FuzzBool(1.0 - self)
        def __and__(self, other):
            return FuzzBool(min(self, other))
        def __or__(self, other):
            return FuzzBool(max(self, other))
        def __repr__(self):
            return "{0}({1})".format(self.__class__.__name__, super().__repr__())
        # 取消float类的加法
        def __add__(self, other):
            raise NotImplementedError
        # 这里还有很多类似的方法要取消...
    f1 = FuzzBool(0.3)
    f2 = FuzzBool(0.5)
    print(f1 | f2)     # 0.5
    print(f1 == eval("FuzzBool(0.3)"))   # True
    FuzzBool继承float
    ####比较:第一种使用聚集的方法创建FuzzBool更好,
    ####因为第二种需要关闭float类的不需要对FuzzBool对象开放的方法

    九、Image类

    import pickle
    '''
    dict.get(key,default)如果value为None将取默认值
    1、图片有背景色,像素颜色跟背景色一样的不保存
    2、__colors属性保存所有不重复的颜色
    '''
    class CoordinateException(Exception):
        pass
    class NotFilenameException(Exception):
        pass
    class SaveException(Exception):
        pass
    class Image:
        def __init__(self, width, height,background="#FFFFFF", filename=""):
            self.filename = filename
            self.__background = background
            self.__width = width
            self.__height = height
            self.__data = {}
            self.__colors = {background}
        @property
        def width(self):
            return self.__width
        @property
        def height(self):
            return self.__height
        @property
        def background(self):
            return self.__background
    
        @width.setter
        def width(self, width):
            self.__width = width
        @height.setter
        def height(self, height):
            self.__height = height
        @background.setter
        def background(self, background):
            self.__background = background
        # 根据像素点的色值 例如:i[40,30]
        def __getitem__(self, item):
            assert len(item) == 2,"should be a 2-tuple"
            if (not (0 <= item[0] < self.width) or
                not(0 <= item[1] < self.height)):
                raise CoordinateException
            return self.__data.get(tuple(item), self.__background)
        # 设置像素点的色值 例如:i[40,30]="#000FFF"
        def __setitem__(self, key, value):
            assert len(key) == 2, "should be a 2-tuple"
            if (not (0 <= key[0] < self.width) or
                    not (0 <= key[1] < self.height)):
                raise CoordinateException
            if value == self.background:
                self.__data.pop(tuple(key))
            else:
                self.__data[tuple(key)] = value
                self.__colors.add(value)
        # 删除像素点
        def __delitem__(self, key):
            assert len(key) == 2, "should be a 2-tuple"
            if (not (0 <= key[0] < self.width) or
                    not (0 <= key[1] < self.height)):
                raise CoordinateException
            self.__data.pop(tuple(key))
        def save(self, filename=None):
            if filename is not None:
                self.filename = filename
            if not self.filename:
                raise NotFilenameException
            f = None
            try:
                f = open(self.filename, "wb")
                data = [self.width, self.height, self.background, self.__data]
                pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)
            except(EnvironmentError,pickle.PicklingError) as err:
                raise SaveException
            finally:
                if f is not None:
                    f.close()
        def load(self, filename=None):
            if filename is not None:
                self.filename = filename
            if not self.filename:
                raise NotFilenameException
            f = None
            try:
                f = open(self.filename, "rb")
                data = pickle.load(f)
                self.width, self.height, self.background, self.__data = data
                self.__colors = (set(self.__data.values()) | {self.background})
            except(EnvironmentError,pickle.PicklingError) as err:
                raise SaveException
            finally:
                if f is not None:
                    f.close()
    i = Image(300, 400)
    # print(i.background)
    # print(i[200,33])
    # i[200,33] = "#000FFF"
    i.load("img.png")
    print(i[200, 33])
    Image类

    十、SortedList排序列表(聚集list)

    class SortedList:
        '''
        实现一个排序列表,列表初始化之后是排过序的。增删改查
        '''
        def __init__(self, sequence=None, key=None):
            __identity = lambda x:x
            self.__key = key or __identity
            assert hasattr(self.__key, "__call__")
            if sequence is None:
                self.__list = []
            elif isinstance(sequence, SortedList) 
                    and self.__key == sequence.key:  # key都为lambda时,表达式为False
                self.__list = sequence.__list[:]   # 可以访问私有变量
            else:
                self.__list = sorted(list(sequence), key=self.__key)
        @property
        def key(self):
            return self.__key
        def add(self, value):
            index = self.__bisect_left(value)
            self.__list.insert(index, value)
        def __bisect_left(self, value):
            '''
            二分法找下标:
            如果key一直落在mid右边,left将以1,1/2,1/4,1/8的速度向右收缩
            如果key一直落在mid左边或等于mid,right将以1,1/2,1/4,1/8的速度向左收缩
            left和right哪边先到达mid=value的下标呢?
            答案一定是left先等于value  因为left是一步一步向右移的 left += 1
            可以看出,如果有相同的value,返回的下标一定是最左边的下标值。
            如果value在list中不存在,将返回value在list中左边值的下标
            '''
            left, right = 0, len(self.__list)
            key = self.__key(value)
            while left < right:
                mid = (left + right) // 2
                if self.__key(self.__list[mid]) < key:
                    left += 1
                else:
                    right = mid
            return left
        def remove(self, value):
            index = self.__bisect_left(value)
            if len(self.__list) > index >= 0 
                and self.__list[index] == value:
                self.__list.pop(index)
            else:
                raise ValueError("{0}.remove(x):x not in list".format(self.__class__.__name__))
        def remove_every(self, value):
            count = 0
            index = self.__bisect_left(value)
            while (0<= index <len(self.__list)
                   and self.__list[index] == value):
                self.__list.pop(index)
                count += 1
            return count
        def count(self, value):
            count = 0
            index = self.__bisect_left(value)
            while (0 <= index < len(self.__list)
                   and self.__list[index] == value):
                index += 1
                count += 1
            return count
        def index(self, value):
            index = self.__bisect_left(value)
            if 0 <= index < len(self.__list) 
                    and self.__list[index] == value:
                return index
            else:
                raise ValueError("{0}.index(x):x not in list.".format(self.__class__.__name__))
        def __delitem__(self, index):
            del self.__list[index]
        def __getitem__(self, index):
            return self.__list[index]
        def __setitem__(self, index, value):
            raise TypeError("use add() to insert a value and rely"
                            " on the list to put it in the right place")
        def __iter__(self):
            return iter(self.__list)
        def __reversed__(self):
            return reversed(self.__list)
        def __contains__(self, value):
            index = self.__bisect_left(value)
            return (0 <= index < len(self.__list) 
                   and self.__list[index] == value)
        def clear(self):
            self.__list = []
        def pop(self, index=-1):
            return self.__list.pop(index)
        def __len__(self):
            return len(self.__list)
        def __str__(self):
            return str(self.__list)
        def copy(self):  # 将首先尝试使用对象的特殊方法__copy__(),如果没有该方法就执行自己的代码
            return SortedList(self.__list)
    
    if __name__ == '__main__':
        s = SortedList([4,2,1,5,7,2,4,6,8])  
        print(s)   # [1, 2, 2, 4, 4, 5, 6, 7, 8]
        print(s.index(1))  # 0
        print(s[2])   # 2
        print(s)    # [1, 2, 2, 4, 4, 5, 6, 7, 8]
        del s[0]
        print(s)    # [2, 2, 4, 4, 5, 6, 7, 8]
        print(600 in s)  # False
        print(s.copy())  # [2, 2, 4, 4, 5, 6, 7, 8]
    SortedList排序列表

    十一、SortedDict排序字典(继承dict聚集SortedList)

    from SortedList import SortedList
    import copy
    class SortedDict(dict):
        def __init__(self, dictionary=None, key=None, **kwargs):
            dictionary = dictionary or {}
            super().__init__(dictionary)  # 如果只到这一句,其实可以不写init方法
            if kwargs:
                super().update(kwargs)
            self.__keys = SortedList(super().keys(), key) # 不能用SortedDict.keys()因为依赖于self.__keys此时还没有keys
        def update(self, dictionary=None, **kwargs): # dictionary可能为None,dict,其他有itmes迭代的类型
            if dictionary==None:
                pass
            elif isinstance(dictionary, dict):
                super().update(dictionary)
            else:
                for key,value in dictionary.items():
                    super().__setitem__(key, value)
            if kwargs:
                super().update(kwargs)
            self.__keys = SortedList(super().keys(), self.__keys.key)
        # @classmethod   # fromkeys方法被继承。类方法比静态方法好,使用类方法可以知道调用该方法的是子类还是父类
        # def fromkeys(cls, iterable, value=None, key=None):
        #     return cls({k: value for k in iterable}, key)
        def __setitem__(self, key, value):
            if key not in self:  # dict类已经实现__contains__方法
                self.__keys.add(key)
            return super().__setitem__(key, value)
        def __delitem__(self, key):
            try:
                self.__keys.remove(key)
            except ValueError:
                raise KeyError(key)
            return super().__delitem__(key)
        def setdefault(self, key, value=None): # 没有key就新增,有key就修改值
            if key not in self:
                self.__keys.add(key)
            return super().setdefault(key, value)
        def pop(self, key, *args):  # *args是为了不关注里面有多少参数都给super处理
            '''
            如果key存在则删除键值对并返回value,如果不存在则返回args[0]
            对比一下两种写法
            if key in self:
                self.__keys.remove(key)
            return super().pop(key, args)
            '''
            if key not in self:
                if len(args) == 0:
                    raise KeyError(key)
                return args[0]
            self.__keys.remove(key)
            return super().pop(key, args)
        def popitem(self):
            item = super().popitem()
            self.__keys.remove(item[0])
            return item
        def clear(self):
            super().clear()
            self.__keys.clear()
        def values(self):        # values迭代器
            for key in self.__keys:
                yield self[key]
        def items(self):         # (key, value)迭代器
            for key in self.__keys:
                yield (key, self[key])
        def __iter__(self):      # keys迭代器
            return iter(self.__keys)
        keys = __iter__          # obj.keys() == iter(obj)
        def copy(self):
            '''
            比较这两种写法:这种需要再进行一次排序,影响效率.
            (ps:只有继承了基本数据类型的才能把self直接进行初始化????)
            return SortedDict(self)
            '''
            d = SortedDict()
            super(SortedDict, d).update(self)  # dict类的update方法
            d.__keys = self.__keys.copy()
            return d
        __copy__ = copy     # copy.copy(obj)将使用自定义的方法
        def value_at(self, index):
            return self[self.__keys[index]]
        def set_value_at(self, index, value):
            self[self.__keys[index]] = value
        def __str__(self):
            return super().__str__() + ' ' + str(self.__keys)
        # def __repr__(self):  # 不能提供eval()的表现形式
        #     return object.__repr__(self)
    # s = SortedDict(dict(A=1,b=2,C=3))
    # print(s)
    
    if __name__ == '__main__':
        s = SortedDict(dict(A=1,b=2,c=3),m=5)
        s1 = SortedDict.fromkeys('abcde', 1) # 调用dict的fromkeys方法
        s2 = dict.fromkeys('abcde', 1)
        print(s1)  # {'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1} ['a', 'b', 'c', 'd', 'e']
        print(type(s1))  # <class '__main__.SortedDict'>
        print(type(s2))  # <class 'dict'>
        s['u'] = 87
        print(s)  # {'A': 1, 'b': 2, 'c': 3, 'm': 5, 'u': 87} ['A', 'b', 'c', 'm', 'u']
        del s['A']
        print(s) #  {'b': 2, 'c': 3, 'm': 5, 'u': 87} ['b', 'c', 'm', 'u']
        print(s.popitem())  # ('u', 87)
        print(s) # {'b': 2, 'c': 3, 'm': 5} ['b', 'c', 'm']
        print(s.keys()) # <list_iterator object at 0x0212F410>
        print(s.copy()) # {'b': 2, 'c': 3, 'm': 5} ['b', 'c', 'm']
        print(copy.copy(s)) # {'b': 2, 'c': 3, 'm': 5} ['b', 'c', 'm']
        print(s.value_at(1))  # 3
        s.set_value_at(1, 99)
        print(s)   # {'b': 2, 'c': 99, 'm': 5} ['b', 'c', 'm']
    SortedDict继承dict
  • 相关阅读:
    eos合约案例导读
    eos TODO EOS区块链上EOSJS和scatter开发dApp
    电脑提示‘您需要来自Administration的权限才能对此文件夹进行更改’怎么删除文件
    ubuntu 设置全局代理
    eos开发实践
    eos博客
    如何在Ubuntu 18.04上安装Go
    parity密码
    Nodejs基础之redis
    完全搞懂事件
  • 原文地址:https://www.cnblogs.com/staff/p/9357116.html
Copyright © 2011-2022 走看看