要一直走下去

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、变量介绍

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

 

posted on 2018-07-23 21:42  要一直走下去  阅读(163)  评论(0编辑  收藏  举报