澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站一品对象,用一等函数落成

2019-09-11 作者:www.8455.com   |   浏览(88)

正文首要内容

经典的“策略”模式

 

python高级——目录

文中代码均位于github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

 

python高等(六)——用一等函数完毕设计方式,python设计方式

正文首要内容

拔尖对象

普普通通函数 & 高阶函数

可调用对象 & 自定义可调用类型

  函数内省

  函数注释

 

python高级——目录

文中代码均位于github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

 

本文重要内容

字符

字节

结构体和内部存款和储蓄器视图

字符和字节之间的转换——编解码器

BOM鬼符

    标准化Unicode字符串

  Unicode文本排序

 

python高级——目录

文中代码均位于github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

 

python高等(三)—— 字典和聚合(泛映射类型),python映射

经典的“策略”模式

'''
    经典的策略模式:
        封装一系列可以互相替代的算法,使得算法可以独立与使用它的客户而变化。


    假设当代商城某服装店有以下三种打折规则:
        1、对于会员,全部商品8.5折
        2、同一件商品买两件及以上,除第一件外,剩余的7.5折
        3、买上5件不同商品,全部商品打8折
    三种规则只能享受一个。
'''


from abc import ABC, abstractmethod
from collections import namedtuple

Customer = namedtuple('Customer', 'name vip')     # 消费者对象


class Clothing:                # 服装类

    def __init__(self, name, quantity, price):
        self.name = name
        self.quantity = quantity
        self.price = price

    def total(self):
        return self.price * self.quantity


class Order:  # 订单类

    def __init__(self, customer, clothing, promotion=None):
        self.customer = customer
        self.clothing = list(clothing)
        self.promotion = promotion

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.clothing)
        return self.__total

    def due(self):
        if self.promotion is None:
            discount = 0
        else:
            discount = self.promotion.discount(self)
        return self.total() - discount

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:.2f}>'
        return fmt.format(self.total(), self.due())


class Promotion(ABC):  # 创建三种折扣的基类

    @abstractmethod
    def discount(self, order):
        ''':returns 计算折扣'''


class VipPromo(Promotion):  # 会员折扣
    """:returns 会员8.5折"""

    def discount(self, order):
        return order.total() * .15 if order.customer.vip  else 0


class TwoPromo(Promotion):  # 第二个
    ''':returns 同一件衣服两件以上,第二件及之后的7.5折'''

    def discount(self, order):
        discount = 0
        for item in order.clothing:
            if item.quantity >= 2:
                discount  = (item.total() - item.price) * .25
        return discount


class FivePromo(Promotion):  # 5种以上
    """ :returns 买5种不同服装以上,每件8折"""

    def discount(self, order):
        distinct_items = {item.name for item in order.clothing}
        if len(distinct_items) >= 5:
            return order.total() * .2
        return 0


if __name__ == "__main__":
    # 创建消费者
    joe = Customer('John Doe', 0)  # 非会员
    ann = Customer('Ann Smith', 1) # 会员

    # 创建购物车
    clothing = [Clothing('pants', 6, 200),
                Clothing('skirt', 1, 150),
                Clothing('shoes', 2, 230)]
    print(Order(joe, clothing, VipPromo()))  #   <Order total: 1810.00 due: 1810.00>    不是会员,不打折
    print(Order(ann, clothing, VipPromo()))  #   <Order total: 1810.00 due: 1538.50>    会员,打85折


    print(Order(joe, clothing, TwoPromo()))  # <Order total: 1810.00 due: 1502.50>   两件以上7.5折
    print(Order(joe, clothing, FivePromo())) # <Order total: 1810.00 due: 1810.00>   没到5种不打折

    clothing.extend([Clothing('shirt', 1, 90), Clothing('bra', 2, 130)])
    print(Order(joe, clothing, FivePromo())) # <Order total: 2160.00 due: 1728.00>  刚好5种打8折
'''
    下面使用函数完成"经典"策略
'''

from abc import ABC, abstractmethod
from collections import namedtuple

Customer = namedtuple('Customer', 'name vip')     # 消费者对象


class Clothing:                # 服装类

    def __init__(self, name, quantity, price):
        self.name = name
        self.quantity = quantity
        self.price = price

    def total(self):
        return self.price * self.quantity


class Order:  # 订单类

    def __init__(self, customer, clothing, promotion=None):
        self.customer = customer
        self.clothing = list(clothing)
        self.promotion = promotion

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.clothing)
        return self.__total

    def due(self):
        if self.promotion is None:
            discount = 0
        else:
            discount = self.promotion(self)
        return self.total() - discount

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:.2f}>'
        return fmt.format(self.total(), self.due())



def VipPromo(order):  # 会员折扣
    return order.total() * .15 if order.customer.vip  else 0


def TwoPromo(order):  # 第二个
    discount = 0
    for item in order.clothing:
        if item.quantity >= 2:
            discount  = (item.total() - item.price) * .25
    return discount


def FivePromo(order):  # 5种以上
    distinct_items = {item.name for item in order.clothing}
    if len(distinct_items) >= 5:
        return order.total() * .2
    return 0



if __name__ == "__main__":
    # 创建消费者
    joe = Customer('John Doe', 0)  # 非会员
    ann = Customer('Ann Smith', 1) # 会员

    # 创建购物车
    clothing = [Clothing('pants', 6, 200),
                Clothing('skirt', 1, 150),
                Clothing('shoes', 2, 230)]
    print(Order(joe, clothing, VipPromo))  #   <Order total: 1810.00 due: 1810.00>    不是会员,不打折
    print(Order(ann, clothing, VipPromo))  #   <Order total: 1810.00 due: 1538.50>    会员,打85折


    print(Order(joe, clothing, TwoPromo))  # <Order total: 1810.00 due: 1502.50>   两件以上7.5折
    print(Order(joe, clothing, FivePromo)) # <Order total: 1810.00 due: 1810.00>   没到5种不打折

    clothing.extend([Clothing('shirt', 1, 90), Clothing('bra', 2, 130)])
    print(Order(joe, clothing, FivePromo)) # <Order total: 2160.00 due: 1728.00>  刚好5种打8折
    promos = [VipPromo, TwoPromo, FivePromo]


    def best_stratety(order):
        return max(promo(order) for promo in promos)


    print(Order(joe, clothing, best_stratety))   # <Order total: 2160.00 due: 1728.00>  自动选择最优的策略
'''
    使用globals函数找出当前的全局号。其返回的是字典格式
'''
promos = [globals()[name] for name in globals()
              if name.endswith("Promo")]

    print(promos)   #  找到了三个策略函数 [<function FivePromo at 0x10c363b70>, <function TwoPromo at 0x10c363ae8>, <function VipPromo at 0x10abd3048>]

    def best_stratety(order):
        return max(promo(order) for promo in promos)

print(Order(ann, clothing, best_stratety))  #<Order total: 2160.00 due: 1728.00>
'''
   我们可以创建一个类,管理所有命令,并且将其实例重写为可调用对象
'''

class MacroCommand:
    def __init__(self, commands):
        self.commands = list(commands)

    def __call__(self):
        for command in self.commands:
            command()

 

正文首要内容

经典的“策略”模式

 

python高级——目录

文中代码均位居github上:

 

头号对象

'''
    在python中,"一等对象"指的是满足下述条件的程序实体:
    (1)在运行时创建
    (2)能赋值给变量或数据结构中的元素
    (3)能作为参数传给函数
    (4)能作为函数的返回结果

    整数、字符串和字典都是一等对象。在面向对象编程中,函数也是对象,并满足以上条件,所以函数也是一等对象,称为"一等函数"
'''


if __name__ == "__main__":
    # 函数的一等性质
    def foo(n):
        '''returns  n!'''
        return 1 if n < 2 else n * foo(n-1)

    print(foo(5))    # 120

    my_foo = foo
    print(my_foo)    # <function foo at 0x1010e3f28> 能赋值给变量
    print(list(map(my_foo, range(6))))   # [1, 1, 2, 6, 24, 120]   能赋值给函数

    def foo2():
        return foo

    my_foo2 = foo2()
    print(my_foo2(5))     # 120 可作为函数的返回结果

 

字符

'''
    字符编码问题是经常困扰python编程人员的问题,我在编写爬虫的过程中也经常遇到这个头疼的事。

    从python3开始,明确区分了人类语言(文本字符串)和机器语言(二进制字节),咱们先说文本字符串
    开始之前,得对"字符"进行定义:
        字符:Unicode字符,从python3的str对象中获取的元素是Unicode字符
        字符串:字符串就是一个字符序列(这里对于(一)中内容相呼应)

'''


if __name__ == "__main__":
    # 创建字符
    s1 = str('a')
    s2 = 'b'
    s3 = u'c'
    print(s1, s2, s3)      # a b c

   

  此时只用记住在python3中字符正是unicode,也正是str是unicode,那是全人类能够看懂的言语。

 

正文主要内容

可散列类型

泛映射类型

字典

    (1)字典推导式

  (2)管理不设有的键

集合

辉映的再谈谈

 

python高级——目录

文中代码均位居github上:

 

python高等连串小说目录

python高级——目录

 

经典的“策略”模式

'''
    经典的策略模式:
        封装一系列可以互相替代的算法,使得算法可以独立与使用它的客户而变化。


    假设当代商城某服装店有以下三种打折规则:
        1、对于会员,全部商品8.5折
        2、同一件商品买两件及以上,除第一件外,剩余的7.5折
        3、买上5件不同商品,全部商品打8折
    三种规则只能享受一个。
'''


from abc import ABC, abstractmethod
from collections import namedtuple

Customer = namedtuple('Customer', 'name vip')     # 消费者对象


class Clothing:                # 服装类

    def __init__(self, name, quantity, price):
        self.name = name
        self.quantity = quantity
        self.price = price

    def total(self):
        return self.price * self.quantity


class Order:  # 订单类

    def __init__(self, customer, clothing, promotion=None):
        self.customer = customer
        self.clothing = list(clothing)
        self.promotion = promotion

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.clothing)
        return self.__total

    def due(self):
        if self.promotion is None:
            discount = 0
        else:
            discount = self.promotion.discount(self)
        return self.total() - discount

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:.2f}>'
        return fmt.format(self.total(), self.due())


class Promotion(ABC):  # 创建三种折扣的基类

    @abstractmethod
    def discount(self, order):
        ''':returns 计算折扣'''


class VipPromo(Promotion):  # 会员折扣
    """:returns 会员8.5折"""

    def discount(self, order):
        return order.total() * .15 if order.customer.vip  else 0


class TwoPromo(Promotion):  # 第二个
    ''':returns 同一件衣服两件以上,第二件及之后的7.5折'''

    def discount(self, order):
        discount = 0
        for item in order.clothing:
            if item.quantity >= 2:
                discount  = (item.total() - item.price) * .25
        return discount


class FivePromo(Promotion):  # 5种以上
    """ :returns 买5种不同服装以上,每件8折"""

    def discount(self, order):
        distinct_items = {item.name for item in order.clothing}
        if len(distinct_items) >= 5:
            return order.total() * .2
        return 0


if __name__ == "__main__":
    # 创建消费者
    joe = Customer('John Doe', 0)  # 非会员
    ann = Customer('Ann Smith', 1) # 会员

    # 创建购物车
    clothing = [Clothing('pants', 6, 200),
                Clothing('skirt', 1, 150),
                Clothing('shoes', 2, 230)]
    print(Order(joe, clothing, VipPromo()))  #   <Order total: 1810.00 due: 1810.00>    不是会员,不打折
    print(Order(ann, clothing, VipPromo()))  #   <Order total: 1810.00 due: 1538.50>    会员,打85折


    print(Order(joe, clothing, TwoPromo()))  # <Order total: 1810.00 due: 1502.50>   两件以上7.5折
    print(Order(joe, clothing, FivePromo())) # <Order total: 1810.00 due: 1810.00>   没到5种不打折

    clothing.extend([Clothing('shirt', 1, 90), Clothing('bra', 2, 130)])
    print(Order(joe, clothing, FivePromo())) # <Order total: 2160.00 due: 1728.00>  刚好5种打8折
'''
    下面使用函数完成"经典"策略
'''

from abc import ABC, abstractmethod
from collections import namedtuple

Customer = namedtuple('Customer', 'name vip')     # 消费者对象


class Clothing:                # 服装类

    def __init__(self, name, quantity, price):
        self.name = name
        self.quantity = quantity
        self.price = price

    def total(self):
        return self.price * self.quantity


class Order:  # 订单类

    def __init__(self, customer, clothing, promotion=None):
        self.customer = customer
        self.clothing = list(clothing)
        self.promotion = promotion

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.clothing)
        return self.__total

    def due(self):
        if self.promotion is None:
            discount = 0
        else:
            discount = self.promotion(self)
        return self.total() - discount

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:.2f}>'
        return fmt.format(self.total(), self.due())



def VipPromo(order):  # 会员折扣
    return order.total() * .15 if order.customer.vip  else 0


def TwoPromo(order):  # 第二个
    discount = 0
    for item in order.clothing:
        if item.quantity >= 2:
            discount  = (item.total() - item.price) * .25
    return discount


def FivePromo(order):  # 5种以上
    distinct_items = {item.name for item in order.clothing}
    if len(distinct_items) >= 5:
        return order.total() * .2
    return 0



if __name__ == "__main__":
    # 创建消费者
    joe = Customer('John Doe', 0)  # 非会员
    ann = Customer('Ann Smith', 1) # 会员

    # 创建购物车
    clothing = [Clothing('pants', 6, 200),
                Clothing('skirt', 1, 150),
                Clothing('shoes', 2, 230)]
    print(Order(joe, clothing, VipPromo))  #   <Order total: 1810.00 due: 1810.00>    不是会员,不打折
    print(Order(ann, clothing, VipPromo))  #   <Order total: 1810.00 due: 1538.50>    会员,打85折


    print(Order(joe, clothing, TwoPromo))  # <Order total: 1810.00 due: 1502.50>   两件以上7.5折
    print(Order(joe, clothing, FivePromo)) # <Order total: 1810.00 due: 1810.00>   没到5种不打折

    clothing.extend([Clothing('shirt', 1, 90), Clothing('bra', 2, 130)])
    print(Order(joe, clothing, FivePromo)) # <Order total: 2160.00 due: 1728.00>  刚好5种打8折
    promos = [VipPromo, TwoPromo, FivePromo]


    def best_stratety(order):
        return max(promo(order) for promo in promos)


    print(Order(joe, clothing, best_stratety))   # <Order total: 2160.00 due: 1728.00>  自动选择最优的策略
'''
    使用globals函数找出当前的全局号。其返回的是字典格式
'''
promos = [globals()[name] for name in globals()
              if name.endswith("Promo")]

    print(promos)   #  找到了三个策略函数 [<function FivePromo at 0x10c363b70>, <function TwoPromo at 0x10c363ae8>, <function VipPromo at 0x10abd3048>]

    def best_stratety(order):
        return max(promo(order) for promo in promos)

print(Order(ann, clothing, best_stratety))  #<Order total: 2160.00 due: 1728.00>
'''
   我们可以创建一个类,管理所有命令,并且将其实例重写为可调用对象
'''

class MacroCommand:
    def __init__(self, commands):
        self.commands = list(commands)

    def __call__(self):
        for command in self.commands:
            command()

 

万般函数 & 高阶函数

'''
    我们一般将函数分为"普通函数"和"高阶函数",接受函数为参数的函数为高阶函数,其余为普通函数

    普通函数大家再熟悉不过,本文不讲,主要讲一下map、filter、reduce三个高阶函数
'''


if __name__ == "__main__":
    # map第一个参数接受一个函数,并将这个函数作用于后面可迭代对象的每一个元素中
    l = map(lambda x : x ** 2, range(11))   # 返回的是生成器类型
    print(list(l))     # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    w = map(str.upper, 'asfafasfasfaf')
    print(list(w))     # ['A', 'S', 'F', 'A', 'F', 'A', 'S', 'F', 'A', 'S', 'F', 'A', 'F']

    # filter第一个参数也接受函数,并返回所有满足该函数的元素
    l = filter(lambda n: n % 2, range(10))   # 返回n % 2为真的数,就是奇数
    l2 = filter(lambda n: n % 2 ==0, range(10))  # 返回偶数
    print(list(l))                           # [1, 3, 5, 7, 9]
    print(list(l2))                          # [0, 2, 4, 6, 8]

    # reduce 从python3开始,reduce放在functools中
    # reduce将某个操作连续应用到序列元素上,即其会将前一步的结果继续应用到下一个元素上
    from functools import reduce
    s = reduce(lambda x,y: x   y, range(101))
    print(s)       # 5050 对1到100求和

 

字节

'''
    python3中内置有两种基本的二进制序列类型:不可变的bytes和可变bytearray
        (1)bytes和bytearray的各个元素是介于0~255(8个bit)之间的整数;
        (2)二进制序列的切片始终是同一类型的二进制序列
'''


if __name__ == "__main__":
    # 创建bytes 和 bytearray
    b1 = bytes('abc你好', encoding='utf8')      # 关于encode稍后会说,不知道有没有人和我一样总是将编码与解码的方向混淆
    print(b1)          # b'abcxe4xbdxa0xe5xa5xbd'

    b2 = bytearray('abc你好', encoding='utf8')
    print(b2)          # bytearray(b'abcxe4xbdxa0xe5xa5xbd')

    # 切片(提示:序列都可以切片)
    print(b1[3:5])     # b'xe4xbd'
    print(b2[3:5])     # bytearray(b'xe4xbd')

    # 使用列表取值的方法试试
    print(b1[3])       # 228 此时取出来的就不是字节序列了,而是一个元素
    for _ in b1:
        print(_, end=',')   # 97,98,99,228,189,160,229,165,189,      这都是8bit的整数

    # bytes的不可变 vs. bytearray的可变

    # b1[3] = 160           # 报错:'bytes' object does not support item assignment
    print(id(b2), b2)      # 4373768376 bytearray(b'abcxe4xbdxa0xe5xa5xbd')
    b2[2] = 78
    print(id(b2), b2)      # 4373768376 bytearray(b'abNxe4xbdxa0xe5xa5xbd')

    # 将b2转换成字符串看看
    print(b2.decode('utf8'))  # abN你好
                              # 注意,这里之所以能够用utf8转成unicode,是因为N的ascii码和utf8一致
    b2.extend(bytearray('添加的内容', encoding='utf8'))  # 既然是可变序列,bytearray当然拥有一般的序列的方法
    print(id(b2), b2)         # 4373768376 bytearray(b'abNxe4xbdxa0xe5xa5xbdxe6xb7xbbxe5x8axa0xe7x9ax84xe5x86x85xe5xaexb9')

    print(b2.decode('utf8'))  # abN你好添加的内容

    # PS:大家可以将二进制序列当成列表,元素就是ascii编码(0~255)

 

可散列类型

'''
    可散列数据类型(也称可hash)————我理解"可散列"就是"可hash"
    可hash的对象需要实现__hash__方法,返回hash值;另外为了与其他对象比较还需要有__eq__方法

    原子不可变数据类型(str、bytes和数值类型)都是可散列的,可散列对象必须满足下列要求:
    (1)实现了__hash__方法,并且所得到的hash值是不变的
    (2)实现了__eq__方法,用来比较
    (3)若a == b 为真,那么hash(a) == hash(b)也是真
'''


# 创建类Foo,并实现__hash__和__eq__

class Foo:
    def __init__(self, name):
        self.name = name

    def __hash__(self):
        print("正在hash...")
        return hash(self.name)

    def __eq__(self, other):
        print("正在比较...")
        return self.name == other.name

    def __repr__(self):
        return self.name


if __name__ == "__main__":

    f1 = Foo("小李")
    f2 = Foo("小红")
    f3 = Foo("小李")

    s = set([f1, f2, f3])        # 集合实现不重复的原理正好利用了散列表
    print(s)                     # {小红, 小李}
    print( f1 == f3, hash(f1) == hash(f3))      # True True 满足可散列对象的第三个条件
'''
    对于元组来说,只有当一个元组包含的所有元素都是可hash的情况下,它才是可hash的
'''
t1 = (1, 2, 3, [1, 2])   # 元组里的列表的值是可变的,所以不可hash
try:
    print(hash(t1))
except Exception as e:
    print(e)             # unhashable type: 'list'

t2 = (1, 2, 3, (1, 2))   # 元组里的元素都是不可变的,并且第二层元组里面的元素也不可变,所以可hash
print(hash(t2))          # 3896079550788208169

t3 = (1, 2, 3, frozenset([1, 2]))
print(hash(t3))          # -5691000848003037416

 

python高档连串小说目录

python高级——目录

 

本文主要内容 杰出的“战略”方式 python高端——目录 文中代码均位于githu...

 可调用对象 & 自定义可调用类型

'''
    我们在使用函数或者实例化对象的时候会用到括号(即()),这个括号实际上是调用运算符,python里面有7中可调用对象:

    1、用户定义的函数
        def和lambda创建
    2、内置函数
        使用C语言实现的函数,如len或time.strftime
    3、内置方法
        使用C语言实现的方法,如dict.get
    4、方法
        在类的定义体中定义的函数
    5、类
        调用类时其实首先运行的是__new__方法,然后运行__init__方法。这里很有意思,自定义类中其实没有重写__new__方法,
        而是调用的超类的__new__方法,如果查看源代码的实现逻辑,相信你会有新的发现,这里不做讨论。
    6、类的实例
        如果类定义了__call__方法,那么它的实例可以作为函数调用
    7、生长器函数
        使用yield关键字的函数或方法。
'''


if __name__ == "__main__":
    # 创建一个自定义可调用类
    class Foo():
        def __init__(self):
            self.name = "Foo"
        def __call__(self, *args, **kwargs):
            print("调用__call__")

    Foo()()     # 输出:调用__call__

    # 以上使用 Foo()() 这种写法看上去很有意思。首先,Foo()会创建一个Foo实例,调用__init__构造方法,; 然后使用实例(),此时
    # 调用__call__方法

 

结构体和内部存款和储蓄器视图

'''
    struct可以从二进制序列中提取结构化信息。
    struct模块提供了一些函数,可以将打包的字节序列转换成不同类型字段组成的元组;还有一些函数用于执行反向转换。
    struct模块可以处理bytes、bytearray、memoryview对象。
'''

import struct

if __name__ == "__main__":
    # memoryview类用于共享内存,可以访问其他二进制序列、打包的数组和缓冲中的数据切片,该操作无需赋值字节序列
    fmt = '<3s3sHH'   # 设置格式,< 是小字节序,3s3s是两个3字节序列,HH是两个16位二进制整数

    with open('L3_图_python.jpg', 'rb') as f:     # 需要在github中下载后运行
        img = memoryview(f.read())

    print(bytes(img[:10]))    # b'xffxd8xffxe0x00x10JFIFx00x01x01x02x00x1cx00x1cx00x00'
    print(struct.unpack(fmt, img[:10]))   # (b'xffxd8xff', b'xe0x00x10', 17994, 17993)  :拆包

    del img

 

泛映射类型

'''
    泛映射类型就是广义上的对应关系,在数学中,我们将集合A对应集合B中的对应法则称为"映射"(Mapping)
    同样,在python里,我们称"键值对"为映射,这其实也是一种对应法则
    如果一个数据类型是映射,那么它肯定属于collections.abc.Mapping,可使用isinstance函数测试

    PS: 字典是 Python 语言中唯一的映射类型。映射类型对象里哈希值(键) 和指向的对象(值)是一对多的关系。
'''

from collections import abc

# 我们测试一些常用的类型是不是映射
if __name__ == "__main__":
    print(isinstance({}, abc.Mapping))      # True   字典是典型的键值对
    print(isinstance([1, 2], abc.Mapping))  # False  列表是序列
    print(isinstance((1, 2), abc.Mapping))  # False  元组是序列
    print(isinstance('adfasfd', abc.Mapping))  # False  字符串也是序列
'''
   大家可以查看_collections_abc.py源代码,里面基本的类型包含:
    ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator",
    "Hashable", "Iterable", "Iterator", "Generator",
    "Sized", "Container", "Callable",
     "Set", "MutableSet",
     "Mapping", "MutableMapping",
     "MappingView", "KeysView", "ItemsView", "ValuesView",
     "Sequence", "MutableSequence",
    "ByteString",
    ]
'''

 

'''
    如果我们自己想定义一个映射类型的对象,那么必须实现__getitem__、__iter__、__len__方法

    PS:关于该部分的原理,本人暂未查看说明文档,毕竟现实中几乎不可能自定义映射;有兴趣的同志可深入钻研。
'''


class Foo(abc.Mapping):
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        return self.name

    def __iter__(self):
        return iter(str(self.name))

    def __len__(self):
        return len(self.name)


print(isinstance(Foo("123"), abc.Mapping))      # True

 

函数内省

'''
    函数内省我们通过例子来看
'''


if __name__ == "__main__":
    # 先创建一个函数
    def foo(n):
        ''':returns n!'''
        return 1 if n<2 else n*foo(n-1)

    print(foo.__doc__)   # :returns n!   __doc__里面存储了注释内容

    # 看看这个函数中有多少属性
    print(dir(foo))
    '''
        ['__annotations__', '__call__', '__class__', '__closure__', '__code__', 
        '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
        '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', 
        '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', 
        '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', 
        '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    '''

    # 下表对一些属性做了说明
名称 类型 说明
__annotations__ dict 参数和返回值的注解
__call__ method-wrapper 实现()运算符
__closure__ tuple 函数闭包
__code__ code 编译成字节码的函数元数据和函数定义体
__defaults__ tuple 形式参数的默认值
__get__ method-wrapper 实现只读描述符协议
__globals__ dict 函数所在模块中的全局变量
__kwdefaults__ dict 仅限关键字形式参数的默认值
__name__ str 函数名称
__qualname__ str 函数的限定名称

 

字符和字节之间的转变——编解码器

'''
    python自带有超过100中编解码器,用于在字符串和字节之间相互转换。
    每个编码都有多个名称,例如'utf_8'、'utf8'、'utf-8'、'U8',这些都可以传递给open()、str.encode()、bytes.decode()中的
    encoding参数
'''


if __name__ == "__main__":
    # 看看不同的编码效果
    for codec in ['gbk', 'utf8', 'utf16']:
        print(codec, "你好".encode(codec), sep='t')
    '''
                        gbk      b'xc4xe3xbaxc3'
                        utf8    b'xe4xbdxa0xe5xa5xbd'
                        utf16    b'xffxfe`O}Y'
    '''
    # 咱们再来解码
    print(b'xc4xe3xbaxc3'.decode('gbk'))            # 你好
    print(b'xe4xbdxa0xe5xa5xbd'.decode('utf8'))   # 你好
    print(b'xffxfe`O}Y'.decode('utf16'))              # 你好
'''
    遇到编码问题一般很烦躁,下面来看看一般怎么解决编码问题。
    (1)UnicodeEncodeError
     (2) UnicodeDecodeError
'''



if __name__ == "__main__":
    # (1)UnicodeEncodeError
    # 使用errors参数
    s1 = "hello,你长胖啦".encode('latin-1', errors='ignore')
    print(s1)   # b'hello'    使用 errors='ignore' 忽略了无法编码的字符

    s2 = "hello,你长胖啦".encode('latin-1', errors='replace')
    print(s2)   # b'hello?????'    使用errors='replace'将无法编码的字符用问好代替

    s3 = "hello,你长胖啦".encode('latin-1', errors='xmlcharrefreplace')
    print(s3)   # b'hello&#65292;&#20320;&#38271;&#32982;&#21862;'  使用errors='xmlcharrefreplace'将无法编码的内容替换成XML实体

    # (2) UnicodeDecodeError
    # 乱码字符称为鬼符,以下实例演示出现鬼符的情况

    s4 = b'Montrxe9al'
    print(s4.decode('cp1252'))    # Montréal
    print(s4.decode('iso8859_7')) # Montrιal
    print(s4.decode('koi8_r'))    # MontrИal
    #print(s4.decode('utf8'))      # 报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte
    print(s4.decode('utf8', errors='replace'))   # Montr�al
    '''
        大多数人都遇到过乱码问题,并且可能总是调试不成功,这可能是各种程序之间的编码不匹配
        以下代码引用自<流畅的python>,可以用来查看当前环境的一些默认编码     
    '''

    # -*- coding: utf-8 -*-

    import sys, locale

    expressions = """
            locale.getpreferredencoding()
            type(my_file)
            my_file.encoding
            sys.stdout.isatty()
            sys.stdout.encoding
            sys.stdin.isatty()
            sys.stdin.encoding
            sys.stderr.isatty()
            sys.stderr.encoding
            sys.getdefaultencoding()
            sys.getfilesystemencoding()
        """

    my_file = open('dummy', 'w')

    for expression in expressions.split():
        value = eval(expression)
        print(expression.rjust(30), '->', repr(value))

    '''
        我电脑运行结果如下:
        (' locale.getpreferredencoding()', '->', "'UTF-8'")
        ('                 type(my_file)', '->', "<type 'file'>")
        ('              my_file.encoding', '->', 'None')
        ('           sys.stdout.isatty()', '->', 'True')
        ('           sys.stdout.encoding', '->', "'UTF-8'")
        ('            sys.stdin.isatty()', '->', 'True')
        ('            sys.stdin.encoding', '->', "'UTF-8'")
        ('           sys.stderr.isatty()', '->', 'True')
        ('           sys.stderr.encoding', '->', "'UTF-8'")
        ('      sys.getdefaultencoding()', '->', "'ascii'")
        ('   sys.getfilesystemencoding()', '->', "'utf-8'")
    '''

字典

'''
    字典是python内置类型中唯一的映射,先看创建字典的几种方法

    1、对象创建
    2、大括号
    3、zip
'''

if __name__ == "__main__":
    # 1、利用实例化对象的方法创建
    a = dict(key1=1, key2=2, all=[1, 2, 3])
    b = dict([('key3', 3), ('key4', 4)])
    c = dict({"key5": 5, "key6": 6})

    print("a:", a)     # a: {'key1': 1, 'all': [1, 2, 3], 'key2': 2}
    print("b:", b)     # b: {'key3': 3, 'key4': 4}
    print("c:", c)     # c: {'key6': 6, 'key5': 5}

    # 2、直接使用大括号
    d = {"key7": 7, "key8": 8}
    print("d:", d)     # d: {'key8': 8, 'key7': 7}

    # 3、使用zip
    e = dict(zip(("key9", "key10", "key11"), [9, 10, 11]))
    print("e:", e)     # e: {'key11': 11, 'key10': 10, 'key9': 9}
'''
    字典推导式:字典推导式的创建方法同列表推导式类似

    以下直接引用《流畅的python》中的例子
'''


if __name__ == "__main__":
    DIAL_CODES = [
        (86, 'China'),
        (91, 'India'),
        (1, 'United States'),
        (62, 'Indonesia'),
        (55, 'Brazil'),
        (92, 'Pakistan'),
        (880, 'Bangladesh'),
        (234, 'Nigeria'),
        (7, 'Russia'),
        (81, 'Japan'),
    ]

    country_code = {country: code for code, country in DIAL_CODES}
    print(country_code)   # {'Russia': 7, 'Indonesia': 62, 'Brazil': 55, 'China': 86, 'India': 91, 'Bangladesh': 880, 'Pakistan': 92, 'United States': 1, 'Nigeria': 234, 'Japan': 81}

    code_upper = {code: country.upper() for country, code in country_code.items() if code < 66}
    print(code_upper)     # {1: 'UNITED STATES', 7: 'RUSSIA', 62: 'INDONESIA', 55: 'BRAZIL'}
'''
    处理找不到的键

    在实际场景中,当使用d[key]的方法查找数据的时候,如果找不到该键,python会抛出KeyError异常;
    如果是取值操作,可以使用d.get(key, default)来解决,可以给找不到的键一个默认的值
    但是如果要给更新某个不存在键对应的值的时候,就稍显麻烦了,可以使用以下方法解决:
        1、用setdefault处理dict找不到的键
        2、使用defaultdict对象
        3、__missing__方法
'''

class Foo:
    def __init__(self, name=None):
        self.name = name

    def __repr__(self):
        return str(self.name)

    def setattr(self, key, value):
        self.__setattr__(key, value)
        return self


if __name__ == "__main__":
    d1 = {}
    print(d1.get("key", "default"))   # default   使用d.get(key, default)的方法取值


    # 1、用setdefault处理dict找不到的键
    d2 = {}
    d2.setdefault("key", [x for x in "adfaf"])  # setdefault虽然是set名字,但是是取值操作,只有当键不存在时才进行赋值,并返回该值
    l = d2.setdefault("key", [])
    print(l)                                    # ['a', 'd', 'f', 'a', 'f']

    d2.setdefault("key2", []).extend([1, 2, 3]) # 返回空列表,所以可在后面直接使用方法extend
    print(d2)                                   # {'key': 'default', 'key2': [1, 2, 3]}

    # 2、使用defaultdict对象
    #  在python中,还有一些dict的变种类型,defaultdict为其中一种,位于collections中
    from collections import defaultdict

    dic = defaultdict(list)                    # 将list的构造方法作为default_factory(只有__getitem__找不到值时调用)
    dic["key"].extend([1, 2, 3])               # dic中不含有"key"键,此时default_factory会被调用,创造一个空列表,并连接[1, 2, 3]
    print(dic["key"])                # [1, 2, 3]

    dic = defaultdict(Foo)           # 将Foo的构造方法作为default_factory创建一个defaultdict
    print(dic["key"].setattr("name", "default"))                # default

    # 3、__missing__方法
    # 所有的映射类型在找不到键的时候,都会牵扯到__missing__方法;如果在__getitem__找不到键的时候,python就会自动调用它
    # 另外,__missing__方法只会被getitem调用,对get或者__contains__没有影响

    class My_dict(dict):
        def __missing__(self, key):
            print("正在调用__missing__...")

    mdict = My_dict(one=1, two=2, three=3)
    print(mdict)     # {'two': 2, 'three': 3, 'one': 1}
    mdict["key"]     # 正在调用__missing__...

 

函数注释

'''
    函数注解很简单,用下面例子简单讲解即可明了
'''


if __name__ == "__main__":
    def foo(num: int, step: 'int 间隔(大于0小于num)'=1) -> int:
        ''':returns 求num的阶乘,可以设置步长'''     # 这里的注释存储在__doc__中
        return num if num <= step else num * foo(num-step,step)

    print(foo(5))  # 120   (5*4*3*2*1)
    print(foo(5, 2))  # 15 (5*3)

    # 函数声明中的各个参数可以在冒号(:)之后增加注释,该注释可以直接写参数类型,也可以写字符串
    # -> 符号后面是对函数返回值进行注解

    # 这些注释内容存储在属性 __annotations__中
    print(foo.__annotations__)  # {'step': 'int 间隔(大于0小于num)', 'num': <class 'int'>, 'return': <class 'int'>}

    # 这样注释后,在使用pycharm时会出现自动提示

 

 

 

BOM鬼符

 ''' 关于BOM的内容比较底层,以下内容全部选自<流畅的python> ''' 

澳门新萄京官方网站一品对象,用一等函数落成设计格局。 

python高级体系文章目录

python高级——目录

 

 

 

字典和集纳(泛映射类型),python映射 本文首要内容 可散列类型 泛映射类型 字典 (1)字典推导式 (2)处理不设有...

python高等连串小说目录

python高级——目录

 

标准化Unicode字符串

'''
    初一看这个标题可能会有点蒙,难道Unicode本身还不够标准么?
    先看看以下的例子:
'''
s1 = 'café'
s2 = 'cafeu0301'
print(s1, s2)     # café café
print(s1 == s2)   # False

'''
    我们发现café可以用'café'和'cafeu0301'两种方式表示,这个词对于人来说是一样的,但是这两种表示对于计算机来说确实不一样的
    向这样的序列叫"标准等价物",在计算机中存储的值不相等,但应用程序应该认为相等。

    要解决这个问题,需要用到unicodedata.nomalize函数,它的第一个参数可以选择这四种形式的一个:"NFC"、"NFD"和"NFKC"、"NFKD"
        "NFC":使用最少的码为构成等价的字符串
        "NFD":把组合的字符分割成基本字符和单独的组合字符

        "NFKC"&"NFKD":这两种是较严格的规范形式,对"兼容字符有影响"
'''

from unicodedata import normalize

if __name__ == "__main__":
    # "NFC" & "NFD"
    print(s1.encode('utf8'), s2.encode('utf8'))   # b'cafxc3xa9' b'cafexccx81'
    s1 = normalize("NFC", s1)
    s2 = normalize("NFC", s2)
    print(s1, s2)    # café café
    print(s1 == s2)  # True
    print(s1.encode('utf8'), s2.encode('utf8'))   # b'cafxc3xa9' b'cafxc3xa9'

    # "NFKC"&"NFKD"
    # 这两种方式会损失信息,所以不建议使用,除非一些特殊情况,比如搜索和索引中
    s3 = '½'
    print(normalize('NFKC', s3))    # 1⁄2    将½转换成了1⁄2
    s4 = '™'
    print(normalize('NFKC', s4))    # TM     将™转换成了TM
    '''
    另外,如果比较的时候不区分大小写,建议使用str.casefold(), 它与lower基本一致,其中大约有116个特殊的字符结果不同
    '''
    s5 = 'AKJkakshfKHDSdshfKSDShKkHkjhKJkgJhgJHkkHkjhJKhKJhK'
    print(s5.casefold())    # akjkakshfkhdsdshfksdshkkhkjhkjkgjhgjhkkhkjhjkhkjhk

 

Unicode文本排序

'''
    python比较序列时,会一一比较其中的元素。对于字符来说,比较的是其码位,主要是比较的ascii码;
    非ascii文本的标准排序方式是使用locale.strxfrm函数,但是使用这个函数必须事先设定区域,但有些操作系统不支持,并且改变区域设置并不十分合适

    建议使用pyuca.Collator.sort_key方法进行排序
'''



if __name__ == "__main__":
    # python默认的排序
    fruits = ['caju', 'atemoia', 'cajá', 'açaí', 'acerola']
    print(sorted(fruits))    # ['acerola', 'atemoia', 'açaí', 'caju', 'cajá']

                            # 但正确排序应该是:['açaí','acerola', 'atemoia', 'cajá', 'caju']

    # 使用pyuca.Collator.sort_key

    import pyuca
    print(sorted(fruits, key = pyuca.Collator().sort_key))   # ['açaí', 'acerola', 'atemoia', 'cajá', 'caju']

    # pyuca可以将自定义排序表路径传递给Collator()构造方法,pyuca默认使用自带的allkeys.txt

 

python高端类别文章目录

澳门新萄京官方网站一品对象,用一等函数落成设计格局。python高级——目录

 

本文由澳门新萄京官方网站发布于www.8455.com,转载请注明出处:澳门新萄京官方网站一品对象,用一等函数落成

关键词: