栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python基础,很详尽!!!(4)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python基础,很详尽!!!(4)

-- # OOP和继承: "is - a"的关系
class A(B):
    pass
a = A()
isinstance(a, B)      # 返回True, A是B的子类 a也是B的一种
# OOP和组合: "has- a"的关系
pass
# OOP和委托: "包装"对象 在Python中委托通常是以"__getattr__"钩子方法实现的, 这个方法会拦截对不存在属性的读取
# 包装类(或者称为代理类)可以使用__getattr__把任意读取转发给被包装的对象
class wrapper:
    def __init__(self, object):
 self.wrapped = object
    def __getattr(self, attrname):
 print('Trace: ', attrname)
 return getattr(self.wrapped, attrname)
# 注:这里使用getattr(X, N)内置函数以变量名字符串N从包装对象X中取出属性 类似于X.__dict__[N]
x = wrapper([1, 2, 3])
x.append(4)    # 返回 "Trace: append" [1, 2, 3, 4]
x = wrapper({'a':1, 'b':2})
list(x.keys()) # 返回 "Trace: keys" ['a', 'b']
-- 类的伪私有属性:使用__attr
class C1:
    def __init__(self, name):
 self.__name = name   # 此时类的__name属性为伪私有属性 原理 它会自动变成self._C1__name = name
    def __str__(self):
 return 'self.name = %s' % self.__name
I = C1('tom')
print(I)# 返回 self.name = tom
I.__name = 'jeey'     # 这里无法访问 __name为伪私有属性
I._C1__name = 'jeey'  # 这里可以修改成功 self.name = jeey
-- 类方法是对象:无绑定类方法对象 / 绑定实例方法对象
class Spam:
    def doit(self, message):
 print(message)
    def selfless(message)
 print(message)
obj = Spam()
x = obj.doit   # 类的绑定方法对象 实例 + 函数
x('hello world')
x = Spam.doit  # 类的无绑定方法对象 类名 + 函数
x(obj, 'hello world')
x = Spam.selfless     # 类的无绑定方法是函数 在3.0之前无效
x('hello world')
-- 获取对象信息: 属性和方法
a = MyObject()
dir(a)  # 使用dir函数
hasattr(a, 'x')# 测试是否有x属性或方法 即a.x是否已经存在
setattr(a, 'y', 19)   # 设置属性或方法 等同于a.y = 19
getattr(a, 'z', 0)    # 获取属性或方法 如果属性不存在 则返回默认值0
#这里有个小技巧,setattr可以设置一个不能访问到的属性,即只能用getattr获取
setattr(a, "can't touch", 100)      # 这里的属性名带有空格,不能直接访问
getattr(a, "can't touch", 0) # 但是可以用getattr获取
-- 为类动态绑定属性或方法: MethodType方法
# 一般创建了一个class的实例后, 可以给该实例绑定任何属性和方法, 这就是动态语言的灵活性
class Student(object):
    pass
s = Student()
s.name = 'Michael'    # 动态给实例绑定一个属性
def set_age(self, age):      # 定义一个函数作为实例方法
    self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s)  # 给实例绑定一个方法 类的其他实例不受此影响
s.set_age(25)  # 调用实例方法
Student.set_age = MethodType(set_age, Student)    # 为类绑定一个方法 类的所有实例都拥有该方法

"""类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题----类的高级话题"""

-- 多重继承: "混合类", 搜索方式"从下到上 从左到右 广度优先"
class A(B, C):
    pass
-- 类的继承和子类的初始化
# 1.子类定义了__init__方法时,若未显示调用基类__init__方法,python不会帮你调用。
# 2.子类未定义__init__方法时,python会自动帮你调用首个基类的__init__方法,注意是首个。
# 3.子类显示调用基类的初始化函数:
class FooParent(object):
    def __init__(self, a):
 self.parent = 'I'm the Parent.'
 print('Parent:a=' + str(a))
    def bar(self, message):
 print(message + ' from Parent')
class FooChild(FooParent):
    def __init__(self, a):
 FooParent.__init__(self, a)
 print('Child:a=' + str(a))
    def bar(self, message):
 FooParent.bar(self, message)
 print(message + ' from Child')
fooChild = FooChild(10)
fooChild.bar('HelloWorld')
-- #实例方法 / 静态方法 / 类方法
class Methods:
    def imeth(self, x): print(self, x)      # 实例方法:传入的是实例和数据,操作的是实例的属性
    def smeth(x): print(x)    # 静态方法:只传入数据 不传入实例,操作的是类的属性而不是实例的属性
    def cmeth(cls, x): print(cls, x) # 类方法:传入的是类对象和数据
    smeth = staticmethod(smeth)      # 调用内置函数,也可以使用@staticmethod
    cmeth = classmethod(cmeth)# 调用内置函数,也可以使用@classmethod
obj = Methods()
obj.imeth(1)    # 实例方法调用 <__main__.Methods object...> 1
Methods.imeth(obj, 2)  # <__main__.Methods object...> 2
Methods.smeth(3)# 静态方法调用 3
obj.smeth(4)    # 这里可以使用实例进行调用
Methods.cmeth(5)# 类方法调用  5
obj.cmeth(6)    #  6
-- 函数装饰器:是它后边的函数的运行时的声明 由@符号以及后边紧跟的"元函数"(metafunction)组成
    @staticmethod
    def smeth(x): print(x)
# 等同于:
    def smeth(x): print(x)
    smeth = staticmethod(smeth)
# 同理
    @classmethod
    def cmeth(cls, x): print(x)
# 等同于
    def cmeth(cls, x): print(x)
    cmeth = classmethod(cmeth)
-- 类修饰器:是它后边的类的运行时的声明 由@符号以及后边紧跟的"元函数"(metafunction)组成
    def decorator(aClass):.....
    @decorator
    class C:....
# 等同于:
    class C:....
    C = decorator(C)
-- 限制class属性: slots属性
class Student:
    __slots__ = ('name', 'age')      # 限制Student及其实例只能拥有name和age属性
# __slots__属性只对当前类起作用, 对其子类不起作用
# __slots__属性能够节省内存
# __slots__属性可以为列表list,或者元组tuple
-- 类属性高级话题: @property
# 假设定义了一个类:C,该类必须继承自object类,有一私有变量_x
class C(object):
    def __init__(self):
 self.__x = None
# 第一种使用属性的方法
    def getx(self):
 return self.__x
    def setx(self, value):
 self.__x = value
    def delx(self):
 del self.__x
    x = property(getx, setx, delx, '')
# property函数原型为property(fget=None,fset=None,fdel=None,doc=None)
# 使用
c = C()
c.x = 100    # 自动调用setx方法
y = c.x      # 自动调用getx方法
del c.x      # 自动调用delx方法
# 第二种方法使用属性的方法
    @property
    def x(self):
 return self.__x
    @x.setter
    def x(self, value):
self.__x = value
    @x.deleter
    def x(self):
del self.__x
# 使用
c = C()
c.x = 100    # 自动调用setter方法
y = c.x      # 自动调用x方法
del c.x      # 自动调用deleter方法
-- 定制类: 重写类的方法
# (1)__str__方法、__repr__方法: 定制类的输出字符串
# (2)__iter__方法、next方法: 定制类的可迭代性
class Fib(object):
    def __init__(self):
 self.a, self.b = 0, 1     # 初始化两个计数器a,b
    def __iter__(self):
 return self # 实例本身就是迭代对象,故返回自己
    def next(self):
 self.a, self.b = self.b, self.a + self.b
 if self.a > 100000:# 退出循环的条件
     raise StopIteration()
 return self.a      # 返回下一个值
for n in Fib():
    print(n) # 使用
# (3)__getitem__方法、__setitem__方法: 定制类的下标操作[] 或者切片操作slice
class Indexer(object):
    def __init__(self):
 self.data = {}
    def __getitem__(self, n):      # 定义getitem方法
 print('getitem:', n)  
 return self.data[n]
    def __setitem__(self, key, value):    # 定义setitem方法
 print('setitem:key = {0}, value = {1}'.format(key, value))
 self.data[key] = value
test = Indexer()
test[0] = 1;   test[3] = '3'# 调用setitem方法
print(test[0])# 调用getitem方法
# (4)__getattr__方法: 定制类的属性操作
class Student(object):
    def __getattr__(self, attr):   # 定义当获取类的属性时的返回值
 if attr=='age':
     return 25# 当获取age属性时返回25
    raise AttributeError('object has no attribute: %s' % attr)
    # 注意: 只有当属性不存在时 才会调用该方法 且该方法默认返回None 需要在函数最后引发异常
s = Student()
s.age  # s中age属性不存在 故调用__getattr__方法 返回25
# (5)__call__方法: 定制类的'可调用'性
class Student(object):
    def __call__(self):     # 也可以带参数
 print('Calling......')
s = Student()
s()    # s变成了可调用的 也可以带参数
callable(s)   # 测试s的可调用性 返回True
#    (6)__len__方法:求类的长度
def __len__(self):
    return len(self.data)
-- 动态创建类type()
# 一般创建类 需要在代码中提前定义
    class Hello(object):
 def hello(self, name='world'):
     print('Hello, %s.' % name)
    h = Hello()
    h.hello() # Hello, world
    type(Hello)      # Hello是一个type类型 返回
    type(h)   # h是一个Hello类型 返回
# 动态类型语言中 类可以动态创建 type函数可用于创建新类型
    def fn(self, name='world'):    # 先定义函数
 print('Hello, %s.' % name)
    Hello = type('Hello', (object,), dict(hello=fn)) 
    # 创建Hello类 type原型: type(name, bases, dict)
    h = Hello()      # 此时的h和上边的h一致

"""异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关----异常相关"""

-- #捕获异常:
    try:
    except:   # 捕获所有的异常 等同于except Exception:
    except name:     # 捕获指定的异常
    except name, value:     # 捕获指定的异常和额外的数据(实例)
    except (name1, name2):
    except (name1, name2), value:
    except name4 as X:
    else:     # 如果没有发生异常
    finally:  # 总会执行的部分
# 引发异常: raise子句(raise IndexError)
    raise  # raise instance of a class, raise IndexError()
    raise     # make and raise instance of a class, raise IndexError
    raise     # reraise the most recent exception
-- Python3.x中的异常链: raise exception from otherException
except Exception as X:
    raise IndexError('Bad') from X
-- assert子句: assert ,
assert x < 0, 'x must be negative'
-- with/as环境管理器:作为常见的try/finally用法模式的替代方案
with expression [as variable], expression [as variable]:
# 例子:
    with open('test.txt') as myfile:
 for line in myfile: print(line)
# 等同于:
    myfile = open('test.txt')
    try:
 for line in myfile: print(line)
    finally:
 myfile.close()
-- 用户自定义异常: class Bad(Exception):.....
"""
Exception超类 / except基类即可捕获到其所有子类
Exception超类有默认的打印消息和状态 当然也可以定制打印显示:
"""
class MyBad(Exception):
    def __str__(self):
 return '定制的打印消息'
try:
    MyBad()
except MyBad as x:
    print(x)
-- 用户定制异常数据
class FormatError(Exception):
    def __init__(self, line ,file):
 self.line = line
 self.file = file
try:
    raise FormatError(42, 'test.py')
except FormatError as X:
    print('Error at ', X.file, X.line)
# 用户定制异常行为(方法):以记录日志为例
class FormatError(Exception):
    logfile = 'formaterror.txt'
    def __init__(self, line ,file):
 self.line = line
 self.file = file
    def logger(self):
 open(self.logfile, 'a').write('Error at ', self.file, self.line)
try:
    raise FormatError(42, 'test.py')
except FormatError as X:
    X.logger()
-- 关于sys.exc_info:允许一个异常处理器获取对最近引发的异常的访问
try:
    ......
except:
    # 此时sys.exc_info()返回一个元组(type, value, traceback)
    # type:正在处理的异常的异常类型
    # value:引发的异常的实例
    # traceback:堆栈信息
-- 异常层次
baseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
    +-- StopIteration
    +-- ArithmeticError
    +-- AssertionError
    +-- AttributeError
    +-- BufferError
    +-- EOFError
    +-- importError
    +-- LookupError
    +-- MemoryError
    +-- NameError
    +-- OSError
    +-- ReferenceError
    +-- RuntimeError
    +-- SyntaxError
    +-- SystemError
    +-- TypeError
    +-- ValueError
    +-- Warning

"""Unicode和字节字符串---Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串----Unicode和字节字符串"""

-- Python的字符串类型
"""Python2.x"""
# 1.str表示8位文本和二进制数据
# 2.unicode表示宽字符Unicode文本
"""Python3.x"""
# 1.str表示Unicode文本(8位或者更宽)
# 2.bytes表示不可变的二进制数据
# 3.bytearray是一种可变的bytes类型
-- 字符编码方法
"""ASCII"""     # 一个字节,只包含英文字符,0到127,共128个字符,利用函数可以进行字符和数字的相互转换
ord('a') # 字符a的ASCII码为97,所以这里返回97
chr(97)  # 和上边的过程相反,返回字符'a'
"""Latin-1"""   # 一个字节,包含特殊字符,0到255,共256个字符,相当于对ASCII码的扩展
chr(196) # 返回一个特殊字符:Ä
"""Unicode"""   # 宽字符,一个字符包含多个字节,一般用于亚洲的字符集,比如中文有好几万字
"""UTF-8"""     # 可变字节数,小于128的字符表示为单个字节,128到0x7FF之间的代码转换为两个字节,0x7FF以上的代码转换为3或4个字节
# 注意:可以看出来,ASCII码是Latin-1和UTF-8的一个子集
# 注意:utf-8是unicode的一种实现方式,unicode、gbk、gb2312是编码字符集
-- 查看Python中的字符串编码名称,查看系统的编码
import encodings
help(encoding)
import sys
sys.platform    # 'win64'
sys.getdefaultencoding()      # 'utf-8'
sys.getdefaultencoding()      # 返回当前系统平台的编码类型
sys.getsizeof(object)  # 返回object占有的bytes的大小
-- 源文件字符集编码声明: 添加注释来指定想要的编码形式 从而改变默认值 注释必须出现在脚本的第一行或者第二行
"""说明:其实这里只会检查#和coding:utf-8,其余的字符都是为了美观加上的"""
# _*_ coding: utf-8 _*_
# coding = utf-8
-- #编码: 字符串 --> 原始字节#解码: 原始字节 --> 字符串 -- Python3.x中的字符串应用
s = '...'# 构建一个str对象,不可变对象
b = b'...'      # 构建一个bytes对象,不可变对象
s[0], b[0]      # 返回('.', 113)
s[1:], b[1:]    # 返回('..', b'..')
B = B"""
    xxxx
    yyyy
    """
# B = b'nxxxxnyyyyn'
# 编码,将str字符串转化为其raw bytes形式:
    str.encode(encoding = 'utf-8', errors = 'strict')
    bytes(str, encoding)
# 编码例子:
    S = 'egg'
    S.encode()      # b'egg'
    bytes(S, encoding = 'ascii')  # b'egg'
# 解码,将raw bytes字符串转化为str形式:
    bytes.decode(encoding = 'utf-8', errors = 'strict')
    str(bytes_or_buffer[, encoding[, errors]])
# 解码例子:
    B = b'spam'
    B.decode()  # 'spam'
    str(B)      # "b'spam'",不带编码的str调用,结果为打印该bytes对象
    str(B, encoding = 'ascii')# 'spam',带编码的str调用,结果为转化该bytes对象
-- Python2.x的编码问题
u = u'汉'
print repr(u)   # u'xbaxba'
s = u.encode('UTF-8')
print repr(s)   # 'xc2xbaxc2xba'
u2 = s.decode('UTF-8')
print repr(u2)  # u'xbaxba'
# 对unicode进行解码是错误的
s2 = u.decode('UTF-8') # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
# 同样,对str进行编码也是错误的
u2 = s.encode('UTF-8') # UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)
-- bytes对象
B = b'abc'
B = bytes('abc', 'ascii')
B = bytes([97, 98, 99])
B = 'abc'.encode()
# bytes对象的方法调用基本和str类型一致 但:B[0]返回的是ASCII码值97, 而不是b'a'
-- #文本文件: 根据Unicode编码来解释文件内容,要么是平台的默认编码,要么是指定的编码类型
# 二进制文件:表示字节值的整数的一个序列 open('bin.txt', 'rb')
-- Unicode文件
s = 'Axc4Bxe8C'      # s = 'A?BèC'  len(s) = 5
#手动编码
    l = s.encode('latin-1')   # l = b'Axc4Bxe8C'  len(l) = 5
    u = s.encode('utf-8')     # u = b'Axc3x84Bxc3xa8C'  len(u) = 7
#文件输出编码
    open('latindata', 'w', encoding = 'latin-1').write(s)
    l = open('latindata', 'rb').read()   # l = b'Axc4Bxe8C'  len(l) = 5
    open('uft8data', 'w', encoding = 'utf-8').write(s)
    u = open('uft8data', 'rb').read()    # u = b'Axc3x84Bxc3xa8C'  len(u) = 7
#文件输入编码
    s = open('latindata', 'r', encoding = 'latin-1').read()   # s = 'A?BèC'  len(s) = 5
    s = open('latindata', 'rb').read().decode('latin-1')      # s = 'A?BèC'  len(s) = 5
    s = open('utf8data', 'r', encoding = 'utf-8').read()      # s = 'A?BèC'  len(s) = 5
    s = open('utf8data', 'rb').read().decode('utf-8')  # s = 'A?BèC'  len(s) = 5

"""其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他----其他"""

-- 60个字符解决FizzBuzz:
"""写一个程序, 打印数字1到100, 3的倍数打印“Fizz”来替换这个数, 5的倍数打印“Buzz”, 既是3又是5的倍数的打印“FizzBuzz”"""
for x in range(101):
    print("fizz"[x%3*4::]+"buzz"[x%5*4::] or x) # 解释:最主要用到列表(字符串)的子表
-- Python实现任意深度的赋值 例如a[0] = 'value1'; a[1][2] = 'value2'; a[3][4][5] = 'value3'
class MyDict(dict):
    def __setitem__(self, key, value):   # 该函数不做任何改动 这里只是为了输出
 print('setitem:', key, value, self)
 super().__setitem__(key, value)
    def __getitem__(self, item):  # 主要技巧在该函数
 print('getitem:', item, self)    # 输出信息
 # 基本思路: a[1][2]赋值时 需要先取出a[1] 然后给a[1]的[2]赋值
 if item not in self:      # 如果a[1]不存在 则需要新建一个dict 并使得a[1] = dict
     temp = MyDict()# 新建的dict: temp
     super().__setitem__(item, temp)     # 赋值a[1] = temp
     return temp    # 返回temp 使得temp[2] = value有效
 return super().__getitem__(item) # 如果a[1]存在 则直接返回a[1]
# 例子:
    test = MyDict()
    test[0] = 'test'
    print(test[0])
    test[1][2] = 'test1'
    print(test[1][2])
    test[1][3] = 'test2'
    print(test[1][3])
-- Python中的多维数组
lists = [0] * 3     # 扩展list,结果为[0, 0, 0]
lists = [[]] * 3    # 多维数组,结果为[[], [], []],但有问题,往下看
lists[0].append(3)  # 期望看到的结果[[3], [], []],实际结果[[3], [3], [3]],原因:list*n操作,是浅拷贝,如何避免?往下看
lists = [[] for i in range(3)]    # 多维数组,结果为[[], [], []]
lists[0].append(3)  # 结果为[[3], [], []]
lists[1].append(6)  # 结果为[[3], [6], []]
lists[2].append(9)  # 结果为[[3], [6], [9]]
lists = [[[] for j in range(4)] for i in range(3)]
lists
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/225997.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号