疯狂python讲义笔记——持续更新至第六章(第三天)

#第一章:绪论
#单行注释
'''
多行注释
'''
"""
多行注释
"""

#dir列出指定类或模块的属性与方法,help查看某个函数或方法的帮助文档
print(dir(str))
print(help(str.title))



#第二章:数据类型
a=5
print(type(a))#
b=5.
print(type(b))#
c=None
print(type(c))#
d='abc'
print(type(d))#
e=str(a)+d
print(e,repr(e),e[1],e[-2],len(e))#5abc '5abc' a b 4
f=''' "I am " a good 'boy' '''
print(type(f),f[11:13])# go
print('od' in f)#True
print('aa' not in f)#True

#输出(好像装了torch后不能Input,算了,反正也用不着控制台)
import sys
f=open("1.txt",'w')
print(a,b,sep='c',end='',file=f,flush=False)#5c5.0
print(a,b,sep=' ',end='\n',file=sys.stdout,flush=False)#5 5.0
#separate分隔符,end结束符,file输出到哪,flush缓冲

#变量名:字母数字下划线,不可数字打头不可如下关键字,可内置函数名但会覆盖
import keyword
print(keyword.kwlist)
'''
['False'假, 'None'空值, 'True'真, 'and'与, 'as'作为, 'assert'异常, 
'break'中断, 'class'类, 'continue'继续, 'def'定义, 'del'删除, 
'elif'否则若, 'else'否则,'except'异常, 'finally'最终, 'for'循环, 
'from'从, 'global'全局, 'if'如果, 'import'导入, 'in'里, 'is'是, 
'lambda'匿名函数,'nonlocal'非本地, 'not'否, 'or'或, 'pass'省略, 
'raise'异常, 'return'返, 'try'异常,'while'当, 'with'伴随, 'yield'生成器]
'''

#转义字符
s='F:\ProjectPython\hello_test'
print(s)#无转义字符
s='F:\rojectPython\bello_test'
print(s)#有转义字符
s=r'F:\rojectPython\hello_test'
print(s)#取消转义字符
'''转义字符
\b退格退一空格,\n换行下一行,\r回车回行首,\t制表输入四个空格
\"双引,\'单引号,\\反斜线
'''

#str封装类的方法
ss='   abc def   '
print(repr(ss.title()))#'   Abc Def   ' 
print(repr(ss.upper()))#'   ABC DEF   '
print(repr(ss.lower()))#'   abc def   '
print(repr(ss.strip()))#'abc def'
print(repr(ss.lstrip()))#'abc def   '
print(repr(ss.rstrip()))#'   abc def'
ss='I love GJL'
print(ss.startswith('I'))#True
print(ss.endswith('GJL'))#True
print(ss.find('o'))#3,找不到返-1
print(ss.index('o'))#3,找不到报错
print(ss.replace('love','like'))#I like GJL
print(ss.split('o'))#['I l', 've GJL']
print(ss.split(None,1))#['I', 'love GJL']
print('.'.join(ss.split(None,1)))#I.love GJL

#运算符
a=5
b=2
c=1/2#若除以0会产生ZeroDivisionError
s='cj'
print("a>b") if a>b else print("ab,在输出层面的三目运算符
print("a>b" if a>b else "ab,先判断返回哪个字符串再输出
print(a,a+b,a-b,a*b,a/b,a//b,a**b,a%b,b*s,s*b)#5 7 3 10 2.5 2 25 1 cjcj cjcj
print(a**c,a&b,a|b,a^b,~a,a<<2,a>>2)#2.23606797749979 0 7 7 -6 20 1
print(a==b,a!=b,a>b,a>=b,a默认是元组
d=['GJL']
print(b+(520,))#('123', '456', '789', 22, 520),相当于append方法,注意(520)是520非元组只是Int
print(a+d)#['abc', 'def', 'ghi', 11, 'GJL'],相当于extend方法
print(d*2)#['GJL', 'GJL']
print(a[0:3:2],b[0:-2:2])#['abc', 'ghi'] ('123',),索引[start:end:step]
print('123' in b,b.index('123'))#True 0,跟前面str很类似
c=[1,3,5,7,9,2,4,6,8,0]
print(len(c))#10

#封包
a_tuple=tuple(range(1,10,2))
a_list=list(range(1,10,2))
print(a_tuple,a_list)#(1, 3, 5, 7, 9) [1, 3, 5, 7, 9]

#解包
a,b,*c,d=a_list#a_tuple也可,*c表示后面若干个的生成一个列表
print(a,b,c,d)#1 3 [5, 7] 9
#封解包结合实例:swap
x,y=1,2
x,y=y,x#swap
print(x,y)#2 1

#列表增删改查(比C++中的链表方便多了)
a=[1,3,4]
b=[25,6,]
a.insert(1,2)
print(a[0],a[1],a[2],a[3])#1 2 3 4,下标越界如访问a[4]会产生IndexError
a.append(b)
print(a)#[1, 2, 3, 4, [25, 6]]
a.extend(b)
print(a)#[1, 2, 3, 4, [25, 6], 25, 6]
del a[2]
print(a)#[1, 2, 4, [25, 6], 25, 6]
del a[2:5:2]
print(a)#[1, 2, [25, 6], 6]
a.remove([25, 6])
print(a)#[1, 2, 6],注意找不到要删除的目标时会报错,此时需要写异常来接收使程序继续
a.sort(reverse=True)#升序
print(a)#[6, 2, 1]
a.reverse()
print(a)#[1, 2, 6]
a.pop()#python真的是一个list就代替了C++中的栈与队列
print(a)#[1, 2]
print(a.count(2))#1
a.clear()#a[0:len(a)+1]=[]是一样的功能
print(a)#[]

#补充一下sort中的key,相当于C++中常写的cmp函数
#第一种是用.sort形式,是类方法会改变类对象自身
a=[]
a.extend(range(1,10,2))
a.extend(range(10,2,-2))
print(a)#[1, 3, 5, 7, 9, 10, 8, 6, 4]
def cmp(x):#自定义比较函数
    return x%3#用%3之后的值来比较
a.sort(key=cmp)#注意当%3后的值相等时按原顺序,即稳定的排序算法
print(a)#[3, 9, 6, 1, 7, 10, 4, 5, 8],默认升序
#第二种是用sorted形式,是全局方法不会改变传入的参数
a=['ab','d','cac']
print(sorted(a,key=len,reverse=True),a)#['cac', 'ab', 'd'] ['ab', 'd', 'cac']

#字典(对应C++中的map),元组可作key因为规定不可变
print(dir(dict))
'clear'#清空
'copy'#复制
'fromkeys'#根据key与val生成字典
'get'#根据key查val,查不到返none,用[]的话会报错KeyError
'items'#获取所有数据对
'keys'#获取所有key
'pop'#由key删除
'popitem'#删除底层存储的最后一个元素
'setdefault'#更新dic,没有该key的话就创建,有该Key的话不修改
'update'#更新dic,没有该key的话就创建,有该Key的话修改为新值
'values'#获取所有val
s='a'
x={1:'ABC',s:'DEF',2:'GHI',4:234}
s='b'#s与x无关
y=x#浅拷贝
z=x.copy()#深拷贝
x[1]='GJL'
print(x)#{1: 'GJL', 'a': 'DEF', 2: 'GHI', 4: 234}
print(y)#{1: 'GJL', 'a': 'DEF', 2: 'GHI', 4: 234}
print(z)#{1: 'ABC', 'a': 'DEF', 2: 'GHI', 4: 234}

#增删改查
x[34]=56
print(x)#{1: 'GJL', 'a': 'DEF', 2: 'GHI', 4: 234, 34: 56}
x[34]=45
print(x)#{1: 'GJL', 'a': 'DEF', 2: 'GHI', 4: 234, 34: 45}
del x[34]
print(x)#{1: 'GJL', 'a': 'DEF', 2: 'GHI', 4: 234}
print(1 in x)#True
print(x.get(4))#234
x.pop(2)#同del x[2]
print(x)#{1: 'GJL', 'a': 'DEF', 4: 234}
x.popitem()
print(x)#{1: 'GJL', 'a': 'DEF'}
x.update({1:'ABC','a':'DEF',2:'GHI'})
print(x)#{1: 'ABC', 'a': 'DEF', 2: 'GHI'}
for i in x.items():
    print(i,i[0],i[1],end=',')#(1, 'ABC') 1 ABC,('a', 'DEF') a DEF,(2, 'GHI') 2 GHI,
    print(type(i))
for i in x.keys():#注意等价于for i in x:即x默认取出来就是Key
    print(i,end=' ')#1 a 2 4
for i in x.values():
    print(i,end=' ')#ABC DEF GHI 234 
my_key = ('G', 'J', 'L')
my_val = 'C','J'
new_dic=dict.fromkeys(my_key, my_val)
print(new_dic)#{'G': ('C', 'J'), 'J': ('C', 'J'), 'L': ('C', 'J')}
new_dic.setdefault('love',520)
print(new_dic)#{'G': ('C', 'J'), 'J': ('C', 'J'), 'L': ('C', 'J'), 'love': 520}
new_dic.setdefault('G',520)
print(new_dic)#{'G': ('C', 'J'), 'J': ('C', 'J'), 'L': ('C', 'J'), 'love': 520}
my_key='my name is %(name)s, my age is %(age)d years old, my weight is %(weight)f kg'
my_val={'name':'CJ','age':24,'weight':50.0}
s=my_key % my_val#这样可以获得一个字符串
print(s)#my name is CJ, my age is 24 years old, my weight is 50.000000 kg

#最后补充四点
#第一点:字典中取出来的数据类型
x={1:'ABC','a':['DEF',45],2:'GHI'}
for i in x.items():
    print(i,i[0],i[1],end=',')
    print(type(i),type(i[0]),type(i[1]))
'''
(1, 'ABC') 1 ABC,  
('a', ['DEF', 45]) a ['DEF', 45],  
(2, 'GHI') 2 GHI,  
'''
#第二点:元组与列表转换元组并非不可改变,及append与extend区别
kk=(12,34)#不可修改的元组
tmp=list(kk)#转换成列表
tmp2=tmp*3
tmp2.append('abc')
tmp2.extend('abc')
print(tmp2)#[12, 34, 12, 34, 12, 34, 'abc', 'a', 'b', 'c']
kk=tuple(tmp2)#再转回元组
print(kk)#(12, 34, 12, 34, 12, 34, 'abc', 'a', 'b', 'c')
#第三点:实现字母遍历用ord字符改ASCII与chrASCII码改字符
s='ABCABCABCDE'
dic={}
for x in range(ord('A'), ord('E') + 1):
    tmp=s.count(chr(x))
    dic[x-64]=tmp
print(dic)#{1: 3, 2: 3, 3: 3, 4: 1, 5: 1}
#第四点:zip写法
a=[1,3,5]
b=[2,4,6]
c=zip(a,b)
print(type(c))#
for x,y in zip(a,b):
    print(x+y)#3 7 11就是打包后再解包得到两个int
for x in zip(a,b):
    print(x,x[0],x[1],type(x))#跟dic一样用一个变量取就是



#第四章:流程控制
if 1:
    pass
elif 1:
    pass
else:
    pass
while 0:
    break
else:
    pass
s='abc'
assert s=='abc'#断言,若不符合会产生AssertionError,若符合则继续往下执行
for i in range(0,len(s),1):
    continue
else:#python中所有循环后都可以用else,其唯一作用是延长这个代码块的临时变量作用域
    print(s[i])#注意i在else块中的值是最后一次符合循环条件的值
for i in s:#除了像上面遍历下标外还可以直接遍历每个元素
    print(i)
b=[(x*x,y) for x in range(2) for y in reversed(range(3))]#for嵌套生成列表
print(b,type(b))#[(0, 2), (0, 1), (0, 0), (1, 2), (1, 1), (1, 0)] 
b=(x*x for x in range(10) if x%2==1)#for与if表达式嵌套生成生成器
for i in b:
    print(i,end=' ')#1 9 25 49 81 
print(b,type(b))# at 0x000001AAC17255C8> 



#第五章:函数
def cjmax(a,b,c,d=2):#痛苦,一开始用了max做函数名覆盖了内置函数致前面第二章处报错
    '''
    return a tuple#返回一个元组
    '''
    return a,b,c,d
print(cjmax.__doc__)#return a tuple#返回一个元组
print(help(cjmax))
'''
Help on function cjmax in module __main__:
cjmax(a, b, c, d=2)
    return a tuple#返回一个元组
None
'''
print(cjmax(1,c=3,b=2))#(1, 2, 3, 2),传参顺序:不带名传参,带名传参(可换位),带默认值的参数(可省)

#四个例子说明传参问题
def cjswap1(w,x,y,z):
    w[0],w[1]=w[1],w[0]
    x[1],x[2]=x[2],x[1]
    y,z=z,y
    w=None#栈中指针清空并不改变指向的堆内存数据
    x=None
w=[8,9]
x={1:2,2:3}
y=6
z=7
cjswap1(w,x,y,z)
print(w,x,y,z)#[9, 8] {1: 3, 2: 2} 6 7,列表字典传参是本体,普通传参是值传递
def cjswap2(*x,y):#用*来传参会打包生成tuple,若后面还有参数传入时必须显式传参如例中的y
    #x[0],x[1]=x[1],x[0]#TypeError: 'tuple' object does not support item assignment
    return x[0],x[1]
x,y=cjswap2(1,2,y=3)
print(x,y)#1 2
def cjswap3(*x,**y):#**y用于收集字典,参数顺序尽量是无*,带*,带**
    print(x)#('I', 'love', 'GJL')
    print(y)#{'cj': 'gjl', 'gjl': 'cj'}
cjswap3('I','love','GJL',cj='gjl',gjl='cj')
def cjswap4(x,y):
    print(x,y)#1 2
cjlist=[1,2]
cjswap4(*cjlist)#带*就是解列表包
cjtuple=(1,2)
cjswap4(*cjtuple)#带*就是解元组包
cjdic={'x':1,'y':2}
cjswap4(**cjdic)#带**就是解字典包

#变量字典
#先弄个全局变量
age=100
name='cj'
love='gjl'
def test(x):
    #print(globals())#全局范围所有变量,输出太多先注释掉
    age=20#默认局变量20遮盖了全局的100
    print(age)#20
    print(globals()['name'])#访问全局变量中变量名为name的变量,cj
    global love#声明本函数作用域内的love用的是全局变量,这就可以对全局变量作修改了
    love='jl'
    print(love)#jl
    print(locals())#局部范围所有变量,在全局范围调用同globals,{'age': 20, 'x': 1}
    print(vars(test))#对象范围所有变量,不传参的话同locas,{}
test(1)
print(age)#100
print(love)#jl

#函数内的函数以及函数换名三方法
def f1(x):
    print(type(x))#由执行时传入参数决定
    def f2(y):
        return y+1
    return f2(x+1)
print(f1(1.0))#3
#一、直接换名
f3=f1
print(f3(1))#3
#二、传参是函数
def f4(f,x):
    return f(x)
print(f4(f3,1))#3
print(type(f4))#
#三、返参是函数
def f5():
    return 1
def f6():
    return f5
f=f6()
print(type(f),f,f())#  1

#lambda
y=lambda x:x*x#单行函数且只用一次
def z(x): return x*x#与上面等价
print(y(2))#4
print(z(2))#4



#第六章:类与对象
#基本属性与方法
class stu:
    def __init__(self,name='cj'):
        self.name=name
    def say(self,content):
        print(self.name,content)
p1=stu()
print(p1.name)#cj
p1.say('loves GJL')#cj loves GJL

#动态增减属性(尽量不用)
p1.age=24#给p1动态增加属性age
del p1.name
print(vars(p1))#{'age': 24}显然p1可以动态增加name属性
p2=stu()
print(vars(p2))#{'name': 'cj'}显然p2并没有age属性即对象之间无影响

#动态增减方法(不能删原有的say)(尽量不用)
#第一种常规
def fun_func1():
    print("running")
p1.run=fun_func1#动态增加方法
p1.run()#running
del p1.run#动态加的方法可以删
#第二种要访问类对象属性时加self
p3=stu()
def fun_func2(self):#若是要访问类属性及类方法记住都加上self
    print(self.name)
p3.introduce=fun_func2
p3.introduce(p3)#cj,必须传p3做参数
#第三种要访问类对象属性时用绑定
from types import MethodType
p4=stu()
p4.introduce=MethodType(fun_func2,p4)
p4.introduce()#cj,绑定后调用时就不用传p4做参数了,跟类定义时就确定的方法一样

#连续调用的写法
class stu2:
    def __init__(self):
        self.age=10
    def grow(self):
        self.age+=1
        return self
cj=stu2()
cj.grow().grow().grow()
print(cj.age)#13

#类调用方法
class stu3:
    def __init__(self,name):#name没有默认值则创建对象时必须构造一个
        self.name=name
    def run():
        print("nobody is running")
    def run2(self):
        print("someone is running")
stu3.run()#nobody is running,类调用方法
stu3.run2(stu3('cj'))#someone is running,有self传入的话也要传入一个

#类方法与静态方法(一般不需要用到,工厂模式下才需要)
class stu4:
    def __init(self):
        self.age=20
    @classmethod
    def run(self):
        pass
    @staticmethod
    def jump(self):
        pass
stu4.run()#类方法与一般对象方法一样是绑定self第一参数传入的
stu4.jump(stu4())#静态方法与类外扩展定义的动态方法是不绑定的所以要传入一个对象

#lambda方法的写法(尽量不用)
class g:
    f=lambda self,p:print(p)
c=g()
c.f(3)#3

#函数装饰器@(尽量不用)
def f1(fn):
    print(1)
    x=fn()
    return x,3
@f1
def f2():
    return 2
print(f2)#1 (2, 3),简单来说就是把执行f2变成执行f1(f2)

#类属性(懂例2即可)
#例1
class stu:
    age=10#这样写就是类属性
p1=stu()#创建对象时由于没有在init中创建对象属性age,所以p1.age就是stu.age
print(p1.age,stu.age)#10 10
stu.age+=1
print(p1.age,stu.age)#11 11
p1.age-=1#一旦p1修改了age就表示他有自己的age了与stu.age无关
print(p1.age,stu.age)#10 11
stu.age+=1
print(p1.age,stu.age)#10 12
#例2
class stu:
    age=10#这样写就是类属性
    def __init__(self):
        self.age=1#在构造函数里带self就是对象属性
p1=stu()
print(p1.age,stu.age)#1 10,显然现在类属性与对象属性就分开得很清楚了
stu.age+=1
print(p1.age,stu.age)#1 11
p1.age-=1
print(p1.age,stu.age)#0 11
stu.age+=1
print(p1.age,stu.age)#0 12
#总结:类变量用类名访问,创建时直接写,对象变量用对象名访问,创建时在init写self.

#property写法(可以封装多个变量变成合成属性,并且增删改查时可以控制权限)
#例1
class stu6:
    def __init__(self,age):
        self.age=age
    def setinfo(self,age):
        self.age=age
    def getinfo(self):
        return self.age
    def delinfo(self):
        self.age=0
    info=property(getinfo,setinfo,delinfo,"someone's age")
print(stu6.info.__doc__)#帮助文档用类访问
help(stu6.info)
p1=stu6(6)
p1.info=8#set
print(p1.info)#8,get
del p1.info#del,不是真删,只是清0
print(p1.info)#0
#例2
class stu7:#用@修饰符写,注意函数名都用age,函数内调用时变量名前加_
    @property#表示get
    def age(self):
        return self._age
    @age.setter#表示set
    def age(self,age):
        self._age=age
p1=stu7()
p1.age=1#set
print(p1.age)#1,get

#封装(与property结合增强安全性)
#隐藏属性
class stu8:
    def __init__(self):
        self.__age=24#变量名前加__就是隐藏属性
        self.__name='cj'
    def setinfo(self,info):
        if info[0]<0 :#输入的元组的第一个元素就是age
            print('error')
            return 
        self.__age,self.__name=info
    def getinfo(self):
        return self.__age,self.__name
    info=property(getinfo,setinfo)#把__age与__name封装成Info并控制读写权限
p1=stu8()
print(p1.info)#(24, 'cj')
p1.info=-1,'gjl'#error
p1.info=23,'gjl'
print(p1.info)#(23, 'gjl')
#特别注意补充说明
p1.__name='newname1'#这里的p1.__name与上面隐藏的self.__name不是同一个变量
print(p1.__name,p1.info)#newname1 (23, 'gjl')
p1._stu8__name='newname2'#这行代码修改的才是隐藏的__name变量
print(p1.__name,p1.info)#newname1 (23, 'newname2')
x,y=p1.info#我再读出来下面比较直白一点
print(p1.__name,y)#newname1 newname2,前者是公开的,后者是隐藏的
print(vars(p1))#{'_stu8__age': 23, '_stu8__name': 'newname2', '__name': 'newname1'}

#隐藏方法
class stu9:
    def __hide(self):
        pass
p1=stu9()
p1._stu9__hide()#执行p1.__hide()会报错AttributeError

#继承
#例1:多继承
class stu10:
    age=10
    def f(self):
        print('stu10',self.age)
class stu11:
    age=11
    def f(self):
        print('stu11',self.age)
class stu12(stu10,stu11):#多继承且有同名属性/方法时以前面的为准,后面的被覆盖
    pass
p1=stu12()
print(p1.age)#10
p1.f()#stu10 10
#例2:重写
class stu13(stu10,stu11):#子类可以重写或覆盖父类的属性/方法
    age=13
    def f(self):
        print('stu13',self.age)
p1=stu13()
print(p1.age)#13
p1.f()#stu13 13,其实与下面这句差不多,只不过调用函数不同,且第一个参数绑定了self
stu10.f(p1)#stu10 13,如果子类对象P1要调用父类方法,直接用类名跑,传子类对象做参数
#例3:super
class stu14():
    def __init__(self,age):
        print('stu14')
        self.age=age
class stu15():
    def __init__(self,name):
        print('stu15')
        self.name=name
class stu16(stu14,stu15):
    def __init__(self,age,name):
        stu14.__init__(self,age)#下面两行代码完全等价
        #super().__init__(age)
        #super(stu16,self).__init__(age)
        stu15.__init__(self,name)
p1=stu16(14,'cj')
print(vars(p1))#{'age': 14, 'name': 'cj'}

#__slots__
'''
一、给对象动态添加的属性/方法,只有此对象有效
二、给类动态添加的属性/方法,对此类全对象有效
三、__slots__限制允许给此类对象(子类无效)动态添加的属性名与方法名,但不限制上面第二点
四、若子类也有__slots__,则子类对象能动态添加的属性名与方法名是子类与父类的__slots__元组和
'''
class stu17:
    __slots__=('walk','age')
p1=stu17()
p2=stu17()
def my_walk(self):
    print('my_walk',self.age)
def my_walk2(self):
    print('my_walk2',self.age)
p1.age=1
p1.walk=my_walk
p1.walk(p1)#my_walk 1
#p2.walk(p2)#AttributeError,证明第一点
stu17.age=17
stu17.walk=my_walk2
p1.walk()#my_walk2 17,证明第二点,且p1.walk()被重写了
p2.walk()#my_walk2 17
#p1.run()=my_walk()#SyntaxError,证明第三点,不能用run方法名因为__元组
class stu18(stu17):
    pass
p1=stu18()
p1.sex='male'#可以用sex属性名,即父类的__slots__无效,证明第三点
class stu19(stu17):
    __slots__=('sex')
    pass
p1=stu19()
#print(p1.sex)#AttributeError: sex,未定义的属性OR方法不用访问
p1.sex='male'#自己的属性可以增加及修改,这行定义之后可以访问执行上一行代码
#p1.age=20
#p1.walk=my_walk#'stu19' object attribute 'walk' is read-only父类slots下的属性OR方法不可修改
print(p1.age)#17
p1.walk()#my_walk2 17,
#一般的来说继承的属性是可以修改的
class A:age=1
class B(A):pass
b=B()
b.age=2
print(vars(b),type(A),type(B))#{'age': 2}  

#type动态创建类
def fn():pass
Dog=type('Dog',(object,),dict(walk=fn,age=6))#类名,父类,成员
d=Dog()
print(type(d),type(Dog),d.age,Dog.age)#  6 6
Cats=type('Cat',(Dog,),dict())#这里是个不好的示范,Cats与'Cat'没有保持一致
c=Cats()
print(type(c),type(Cats),c.age,Cats.age)#  6 6
#事实证明,函数内用CALSS定义类也是可以的,比上面的写法更清晰
def kkk():
    class A:
        print('hi')
kkk()#hi

#metaclass
class stu20(type):
    def __new__(cls,name,bases,attrs):
        attrs['cal']=lambda self:self.age+1
        def f(self):
            self.age+=1
        attrs['cal2']=f
        return type.__new__(cls,name,bases,attrs)
class stu21(metaclass=stu20):
    def __init__(self):
        self.age=1
p1=stu21()
print(vars(p1))#{'age': 1}
p1.age=p1.cal()
print(vars(p1))#{'age': 2}
p1.cal2()
print(vars(p1))#{'age': 3}

#多态
class stu21:
    color='red'
    def paints(self,pattern):#提供接口,画什么收传入的类对象pattern来定
        pattern.paint(self)#这里传进去的self是stu21类的self,即下面的pic传入参数
class triangle:
    def paint(self,pic):
        print('draw triangle',pic.color)
class rectangle:
    def paint(self,pic):
        print('draw rectangle',pic.color)
class circle:
    def paint(self,pic):
        print('draw circle',pic.color)
p1=stu21()
p1.paints(triangle())#draw triangle red
p1.paints(rectangle())#draw rectangle red
p1.paints(circle())#draw circle red

#检查类型
class stu22:
    age=10
class stu23(stu22):pass
print(issubclass(stu23,stu22))#True,是子类
p1=stu22()
print(isinstance(p1,stu22))#True,是该类对象
#特别补充说明
#一、object类是所有类的基类
#issubclass(a,b)若a是b的派生类则返True(子孙类)
print(issubclass(int,object))#True
print(issubclass(float,object))#True
print(issubclass(str,object))#True
print(issubclass(list,object))#True
print(issubclass(tuple,object))#True
print(issubclass(dict,object))#True
print(issubclass(type,object))#True
print(issubclass(stu22,object))#True
print(issubclass(stu23,object))#True
#二、class及type定义出来的类其实是type这个类的对象
#isinstance(a,b)若a对象是b类的实例则返True
print(isinstance(type,type))#True
print(isinstance(stu22,type))#True
print(isinstance(stu23,type))#True
#三、直接父类查询用__bases__
print(stu23.__bases__)#(,)
print(stu22.__bases__)#(,)
print(object.__bases__)#()
print(type.__bases__)#(,)
print(int.__bases__)#(,)
print(float.__bases__)#(,)
print(str.__bases__)#(,)
print(list.__bases__)#(,)
print(tuple.__bases__)#(,)
print(dict.__bases__)#(,)
print(type.__bases__)#(,)
#lh 、直接子类查询用__subclasses__
print(stu23.__subclasses__())#[]
print(stu22.__subclasses__())#[]
x=stu22.__subclasses__()
print(type(x),type(x[0]))# 
#print(type.__subclasses__())#会报错缺少argument,即type没有子类,但其对象可有子类
#print(object.__subclasses__())输出太多了,先注释掉这行

#枚举类(尽量不用)
#写法一
import enum
Seasons=enum.Enum('Season',('SPRING','SUMMER','FALL','WINTER'))
print(Seasons,type(Seasons))# 
print(Seasons.SPRING,type(Seasons.SPRING))#Season.SPRING 
print(Seasons.SPRING.name,Seasons.SPRING.value)#SPRING 1
print(Seasons['SUMMER'])#Season.SUMMER,根据name找元素
print(Seasons(3))#Season.FALL,根据value找元素
for name,member in Seasons.__members__.items():#返回的元组元素是(name,枚举元素)
    print(name,member,member.value)#……WINTER Season.WINTER 4
#Season是创建的一个枚举类enum.EnumMeta,Seasons相当于话柄(其实用同名更好)
#四季的单词是这个类的四个枚举元素,类型是Season
#每个元素下又有两个成员,name与value,这就是基本数据类型了
#写法二
import enum
class Orientation(enum.Enum):
    one=1
    two=2
    three=3
    def __init__(self,x):
        self.age=x+10
    def getage(self):
        return self.age
    def info(self):
        print(self.value)
print(Orientation.two,type(Orientation.two))#Orientation.two 
print(Orientation.two.name,type(Orientation.two.name))#two 
print(Orientation.two.value,type(Orientation.two.value))#2 
print(Orientation['two'],type(Orientation['two']))#Orientation.two 
print(Orientation(2),type(Orientation(2)))#Orientation.two 
Orientation.two.info()#2
for name,member in Orientation.__members__.items():
    print(name,member,member.value)
'''
one Orientation.one 1
two Orientation.two 2
three Orientation.three 3
'''
print(Orientation.two.getage())#12



print()
print()
print()



#第七章






























 

你可能感兴趣的:(2020年暑假研零笔记)