• 【Python047-魔法方法:定制序列】


    一、协议是什么

    1、协议(protocols)与其他编程语言中的接口很相似,它规定你那些方法必须要定义。然而在Python中协议就显的不那么正式,事实上,在Python中,协议更像是一种指南

    2、容器类型的协议

    ** 如果你希望定制的容器是不可变的话,那你只需要定义__len__(),和__getitem__()方法

    ** 如果你希望定制的容器是可变的话,那你除了定义__len__() 和__getitem__()方法外,还需要定义__setitem__()和 __delitem__()两个方法

    3、容器类型

    __len__(self)          定义当被len()调用时的行为(返回容器中元素的个数)

    __getitem__(self,key)      定义获取容器中指定元素的行为,相当于self[key]

    __setitem__(self,key,value)    定义设置容器中指定元素的行为,相当于self[key] = value

    __delitem__(self,key)      定义删除容器中指定元素的行为,相当于del self[key]

    __item__(self)          定义当迭代容器中元素的行为

    __reversed__(self)          定义当被reversed()调用时的行为

    __contains__(self,item)       定义当使用成员测试运算符(in 或 not in)时的行为

    魔法方法详解:https://fishc.com.cn/thread-48793-1-2.html

    二、 编写一个不可改变的自定义列表,要求记录列表中每个元素被访问的次数

    #定制一个不可改变的列表,并且记录每个元素的访问次数
    class CountList:
        def __init__(self,*args):#不知道需要传入多少个参数,那么就设置一个可变的参数集
            self.values = [x for x in args]#列表推导式
            #用列表推导式遍历用户传入的参数并建立一个列表
            #self.value里面的内容是用户传入的参数
            print("self_value++",self.values)
            self.count = {}.fromkeys(range(len(self.values)),0)
            #用fromey()方法建立一个字典,self.count是字典
            #字典的key是self.value的索引,对应的value值分别初始化为0
            print("self.count--",self.count)
    
        def __len__(self):
            return len(self.values) #当len被调用时,返回了容器中元素的个数
    
        def __getitem__(self,key):
            #这里用户想要得到某个参数的访问次数,需要传入该参数的索引值
            self.count[key] +=1 #每访问一次key对应的value就记录一次
            return self.values[key]
          
    执行结果:
    >>> c1 = CountList(1,3,5,7,9)
    self_value++ [1, 3, 5, 7, 9]
    self.count-- {0: 0, 1: 0, 2: 0, 3: 0, 4: 0}
    >>> c1[1]
    3
    >>> c1.count
    {0: 0, 1: 1, 2: 0, 3: 0, 4: 0}
    >>> c1[1]
    3
    >>> c1.count
    {0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
    >>> c1[1]
    3
    >>> c1.count
    {0: 0, 1: 3, 2: 0, 3: 0, 4: 0}
    
    '''
    |-- 由打印出来的结果:
    |-- self_value++ [1, 3, 5, 7, 9]
    |-- self.count-- {0: 0, 1: 0, 2: 0, 3: 0, 4: 0}
    |-- 可以得知,列表里面放的是传入的参数,只不过是已列表推导式形成一个列表,字典里面放的是列表的索引以及访问列表内属性的次数,默认为0
    |-- 采用__len__():当len被调用时,返回了容器中元素的个数
    |-- 为了实现每访问一次元素,就使访问的次数叠加1,必须传入字典self.count的key,并且逐步+1:self.count[key] +=1
    '''

    三、python中统计list中各元素出现的此时

    1、利用python字典统计

    2、利用python的collection中的Counter的类统计

    3、利用python的panda包下的value_counts的类统计

    #利用python字典统计
    a = [1,2,3,1,2,5] dict = {} for key in a: dict[key] = dict.get(key,0)+1 print(dict)

    执行结果:
    {1: 2, 2: 2, 3: 1, 5: 1
    #利用python的collection中的Counter的类统计

    from
    collections import Counter a =[2,2,2,3,3,4,5] result = Counter(a) print(result) 执行结果: Counter({2: 3, 3: 2, 4: 1, 5: 1})
    #利用pandas包下的value_counts方法
    import pandas as pd
    a = [2,2,33,4,5,5]
    result = pd.value_counts(a)
    print(result)
    
    
    执行结果:
    5     2
    2     2
    4     1
    33    1
    dtype: int64
    >>> 
    #panda包的value_counts()方法不仅可以统计list中元素出现的次数,还可以对矩阵元素进行统计
    import pandas as pd
    a = pd.DataFrame([[1,2,3],
                     [3,1,3],
                     [1,2,1]])
    result = a.apply(pd.value_counts)
    print(result)
    
    执行结果:
         0    1    2
    1  2.0  1.0  1.0
    2  NaN  2.0  NaN
    3  1.0  NaN  2.0

    四、读取数据库内的数据,并且统计数据库内某一列元素出现的次数(大约100w条数据)

    from collections import Counter
    import pandas as pd
    import numpy
    import time
    
    #随机生成一个含有一百万整数的列表
    def get_random_list():
        numpy.random.seed(10)
        return numpy.random.randint(0,1000000,1000000)
    
    #第一种方法:字典
    def get_list(l):
        dict = {}
        t1 = time.time()
        for i in l:
            if i in dict.keys(): #判断元素是否在字典内,如果在则对应的value+1
                dict[i] = int(dict[i])+1
            else:
                dict[i] = 1  #如果不在,字典中新增对应的items
    
        t2 = time.time()
        #print("list_dict==",dict)
        print("list_time==",t2-t1)
    
    #第二种方法:采用list的count()函数:用于统计某个元素在列表内出现的次数
    def get_count_py_count(l):
        dict = {}
        t1 = time.time()
        s = set(l) #集合:得到不重复的元素
    
        for i in s:
            #解决:AttributeError: 'numpy.ndarray' object has no attribute 'count错误的方法:增加一个tolist()函数
            dict[i] = l.tolist().count(i) #对集合中的每一个元素分别计数,存入dictionary中
    
        t2 = time.time()
        print("count_time:",t2-t1)
        return dict
    
    '''
    |-- 第三种方法:采用collections的Counter类
    |-- Counter(l)统计列表内数字出现的次数,然后放入字典内:dict(count)
    '''
    def get_count_py_counter(l):
        t1 = time.time()
        count = Counter(l)
        t2 = time.time()
        print("counter_time++",t2-t1)
        count_dict = dict(count)
        return count_dict
    
    '''
    |-- 第四种方法:采用pandas包的value_counts方法
    |-- pd.value_counts(l)统计列表内数字出现的次数,然后放入字典内:dict(count)
    '''
    def get_count_py_pandas(l):
        t1 = time.time()
        count = pd.value_counts(l)
        t2 = time.time()
        print("pandas_time--",t2-t1)
        count_dict = dict(count)
        return count_dict
    
    if __name__ == "__main__":
        l = get_random_list()
        get_list(l)
        #print("出现的次数:",l.tolist().count(355353))
        #get_count_py_count(l)
        get_count_py_counter(l)
        get_count_py_pandas(l)
        
    执行结果:
    list_time== 1.8361890316009521
    counter_time++ 0.8999738693237305
    pandas_time-- 0.28310179710388184
    
    '''
    |-- 由字典统计次数时间,Counter统计时间和value_counts统计时间可以看出:100万数据,pandas的统计时间是最短的
    '''

      

  • 相关阅读:
    纯JS实现中国行政区域上下联动选择地址
    java解析中国行政区域并在页面显示实现动态逐级筛选
    使用HttpClient 发送get、post请求,及其解析xml返回数据
    JS实现动态提示文本框可输入剩余字数(类似发表微博数字提示)
    webApi 数据绑定 获取
    EF Code First 常用命令
    [解决WebClient或HttpWebRequest首次连接缓慢问题]
    【转】Entity Framework技术系列之7:LINQ to Entities
    Ajax方法提交整个表单的信息
    【转】MVC中处理Json和JS中处理Json对象
  • 原文地址:https://www.cnblogs.com/frankruby/p/9992557.html
Copyright © 2020-2023  润新知