# -*- coding: utf-8 -*-
print('*'*20, '列表环节', '*'*20)
# append()函数向列表末尾添加一个元素.
# extend()函数向列表末尾添加多个元素.
# insert(n,xxx)函数向列表中第n个元素前插入一个元素.
L = []
for i in range(0, 5):
L.append(i)
print(L)
L.insert(1, 5)
L.insert(2, '5')
L.extend([8, '10'])
print(L)
# remove()函数表示从列表中删除某个元素.
# del()函数也表示从列表中删除某个元素.
# pop()函数从列表中取出最后一个元素.
if i in L:
if i == 1:
L.remove(1)
if i == 8:
index = L.index(8)
del L[index]
if i == 4:
L.pop(-3)
L.insert(3, 1)
print(L)
L.pop(3)
L.append(1)
L.extend(['111', 1])
print(L)
# 列表分片.
print(L[0:5])
# 列表进行拷贝.
mix = L[0:5]
print(mix)
# 比较操作符.
print(L > mix) # L 包含了 mix
# 成员关系操作符.
print('111' in L)
# dir(list)可查看所有列表的操作函数(方法).
# print(dir(L))
print(L.count(1)) # 列表中出现3次1.
print(L.index(1)) # index()函数可索引列表元素.
K = L[3:7]
# print(dir(K))
# print(dir(K.reverse()))
K.reverse()
print(K)
# sort()将列表中元素从小到大排序.
K.sort()
print(K)
print('*'*20)
# 关于分片'拷贝'概念的补充.
K.reverse()
list11 = K
list22 = list11
list33 = list11[:]
print(list11)
print(list22)
print(list33)
print('*'*20, '分片“拷贝”概念的补充.') # 注:list22=list11相当于多了个指向列表的标签,list12 = list[:]是实实在在的拷贝
list11.sort()
list11.append('222')
list11.insert(0, '0') # 查看id可知.list22=list11相当于多指向,id相同.
print(list11, id(list11))
print(list22, id(list22))
print(list33, id(list33))
print('*'*20, '列表环节', '*'*20)
print('*'*20, '元组环节', '*'*20)
# 元组和列表是近亲关系,所以在实际使用上是非常类似的.
T = (5, 4, 3, 2, 1)
print(T)
# 元组的分片.
print(T[:2])
# 更新和删除一个元组. # 注:其并未对原元组进行修改,而是生成了一个新的元组,并贴上temp名字标签而已。原元组由于标签没有了,则会被自动回收。
T = T[:2] + (10, ) + T[2:]
print(T)
del T
# 注:元组不允许修改和删除。
# 格式化.
print('%5.2f' % 27.625)
# 序列!!!
T = (4, 3, 2, 1)
print(T)
# max() 返回序列或者参数集合中的最大值. # min() 返回序列或者参数集合中的最小值.
print(max(T), min(T))
# sum(iterable[,start=0]) 返回序列iterable和可选参数start的总和.
print(sum(T), sum(T, 5))
# sorted()将元素从小到大重新排列.(注:元组是不可以修改和删除的,所以不可以直接对元组使用sorted与reversed命令)
print(sorted(T)) # 以列表的形式返回,并进行了排序.
# reversed()将元素倒序排列.
# print(dir(reversed))
print(reversed(sorted(T))) # 返回一个列表倒序对象.
# for i in reversed(sorted(T)):
# print(i)
print(list(reversed(sorted(T))))
print(reversed(T))
print(tuple(reversed(T)))
# for i in reversed(T): # 返回一个元组倒序对象.
# print(i)
# enumerate()将每个元素插入枚举.
num = sorted(T)
# print(dir(enumerate(num))) # 具备'__iter__'、'__next__',则是一个迭代器,可以进行遍历输出.
print(enumerate(num)) # 返回一个对象.也可以用遍历的方式把内容遍历出来.
print(list(enumerate(num)), '对象', tuple(enumerate(num)))
for i in enumerate(T):
print(i[0], num[i[0]])
# zip()返回由各个参数的序列组成的元组.
nam = sorted(T)[:] # 进行'分片'拷贝,实实在在的拷贝,不是让列表指向多个标签.
# print(num, nam)
# print(list(reversed(num)))
print(zip(list(reversed(num)), nam)) # 返回一个zip()对象.
print(list(zip(list(reversed(num)), nam)), '对象', tuple(zip(list(reversed(num)), nam)))
print('*'*20, '元组环节', '*'*20)
# 关于函数收集参数.
def test(*params):
print('参数的长度是:', len(params))
print('第二个参数是', params[1])
test(1, 2, 3, 4, 5, 6)
def back():
print('255')
return [7, 8, 9]
# back()
# print(back())
B = back() # B = back()实例化对象。返回:函数内容.
print(B, '返回值', B[2]) # 返回:函数的返回值.
# 内嵌函数和闭包.
# 内嵌函数.
def fun1():
print('fun1()被调用')
def fun2():
print('fun2()被调用')
def fun3():
print('fun3()被调用')
fun2()
return fun3
# print(fun1().__dir__())
# fun1()
print(fun1())
# f = fun1()
# print(f) # 返回函数fun3方法对象.
# 闭包.
def ind(x):
def fun11(y):
return x * y
return fun11
print(ind(5)(8))
# ind = ind(5)
# print(ind(8))
# nonlocal语句将x强制为不是局部变量.
def non():
x = 5
def non1():
nonlocal x
x *= x
return x
return non1()
print(non())
# global可将局部变量声明为全局变量.
count = 5
def fun4():
global count
count = 10
print(count)
fun4()
print(count)
# 匿名函数:lambda表达式.
g = lambda x: 3 * x + 2 # 相当于 def 匿名(x): return 3 * x + 2.
print(g(3))
# 过滤函数filter()可筛选出非零元素.
# filter函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,
# 最后将返回 True 的元素放到新列表中,就好比是用筛子,筛选指定的元素;
# 语句:filter(function, iterable)
T = (None, [1, 0], True, False)
print(type(T))
print(filter(None, [1, 0, True, False])) # 返回一个filter对象.
# print(filter(lambda x: x % 2, [1, 2, 3, 4, 5]))
print(list(filter(lambda x: x % 2, [1, 2, 3, 4, 5])))
print(list(filter(None, [1, 2, 3, 0, 5])))
# print(dir(filter(None, [1, 0, True, False]))) # 查看对象属性(方法).
# for i in filter(None, [1, 0, True, False]): # 对对象进行遍历.
# print(i)
# print(list(filter(None, [1, 0, True, False])), '对象', tuple(filter(None, [1, 0, True, False])))
def is_odd(n):
return n % 2 == 1
tmp = filter(is_odd, range(10))
print(tmp)
print(list(tmp))
print('*'*20)
# iter()函数和next()用来生成迭代器.
ls = [1, 2, 3, 4, 5]
# print(dir(lis))
it = iter(ls)
print(it) # 列表形式的迭代器对象.
print(next(it))
print(next(it))
for i in it:
print(i, end=' ')
print('*'*20)
ls = [1, 2, 3, 4, 5]
it = iter(ls)
while True:
try:
x = next(it)
print(x, end=' ')
except StopIteration:
# 遇到StopIteration就退出循环
break
print('*'*20)
class MyNumbers(object):
def __iter__(self):
self.a = 1
return self
def __next__(self):
global x
x = self.a
self.a += 1
return x
myclass = MyNumbers() # 实例对象.
myiter = iter(myclass) # 创建迭代器对象.
print(next(myiter))
print(next(myiter))
print(next(myiter))
print('*'*20)
class MyIter(object): # 我限制循环次数,超出则抛出错误.
def __iter__(self):
self.a = 1
return self # 返回实例对象
def __next__(self):
global x
x = self.a
self.a += 1
if x >= 3:
raise StopIteration('抛出一个异常') # 异常抛出print()不会执行.
else:
return x
My = MyIter() # 实例对象.
ie = iter(My) # 创建迭代器对象.
# print(next(ie))
# print(next(ie))
# print(next(ie)) # 第三次时会出错.
for i in ie:
print(i)
print('*'*20)
class ItIter(object): # 类似于上面while为了防止报错.
def __iter__(self):
self.a = 1
return self
def __next__(self):
global x
x = self.a
while True:
self.a += 1
try:
if x >= 3:
raise StopIteration('抛出一个异常')
else:
return x
except StopIteration:
break
return
MyIe = ItIter()
Ie = iter(MyIe)
print(next(Ie))
print(next(Ie))
print(next(Ie))
print('*'*20)
# 生成器内容.
def func():
print('内容1')
yield 1
print('内容2')
yield 2
print('内容3')
f = func()
print(f) # 返回一个迭代器对象.然后用迭代器next()方法输出.不用进行iter()方法进行创建迭代器对象.
# print(dir(f))
print(next(f))
print(f.__next__())
# print(f.__next__()) # 也报错了,没有迭代器对象了.
# print(f.__next__()) # 再次运行则报错.
print('*'*20)
import sys
def fib(n):
global x
x = 0
while True:
if n < 0:
print('不能为负数.')
yield n
if x <= n:
print('内容%s' % x) # 为了更加方便观察.
yield x # 返回一个迭代器对象.
else:
return # 上半部分主要用于形成迭代器对象.
x += 1
ib = fib(-1)
print(ib.__next__())
ib = fib(2)
print(ib.__next__())
print(ib.__next__())
print(ib.__next__())
# print(ib.__next__()) # 这次报错.
print('*'*20)
ib = fib(2)
print(ib) # 返回一个迭代器对象.
# print(dir(ib)) # 查看对象的属性(方法).
# for i in ib: # for循环直接遍历出来.
# print(i)
while True:
try:
print(next(ib))
except StopIteration:
# sys.exit() # 直接结束python让后续的命令不能运行.
break
print('*'*20)
# 生成器表达式.
# collections是一个包含了许多类型的module包
from collections.abc import Iterator, Iterable, Generator
g = (i**2 for i in range(1, 6) if i > 3) # 返回一个迭代器对象.
print(g)
# print(isinstance(g, Iterable)) # 迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象.
# print(dir(g))
# print(next(g))
for i in g:
print(i, end=' ')
print('*'*20)
# print(dir(list)) # 只含有__iter__为可迭代对象.
ls = [1, 2, 3] # 可以看到这是一个可迭代对象但并不是迭代器,我们把它搞成一个迭代器试试看.
print('迭代器对象:', isinstance(ls, Iterator), '可迭代对象', isinstance(ls, Iterable), '生成器:', isinstance(ls, Generator))
def generator_list(a):
for e in a:
yield 'Province:\t' + str(e)
for province in generator_list(ls):
print(province)
gen = generator_list(ls)
print(gen)
print(isinstance(generator_list(ls), Iterator), isinstance(generator_list(ls), Iterable), isinstance(generator_list(ls), Generator))
# print(dir(generator_list(ls)))
print(next(gen))
print(next(gen))
print(next(gen))
# print(ls) # 可迭代对象.具备__iter__属性(方法).
lls = iter(ls) # iter()方法的用处.第一个参数需要是具备属性可迭代对象的变量.
# print(dir(lls)) # 迭代器对象.具备'__iter__'、'__next__'属性(方法).
print('*'*20)
class TextIter(object):
def __init__(self):
self.a = [1, 2, 3]
self.b = iter(self.a) # 迭代器对象.
def __iter__(self):
print('__iter__方法')
return iter(self.a) # 返回迭代器对象.
def __call__(self):
item = next(self.b)
print('__call__方法')
return item # 返回迭代器函数next().
# print(dir(TextIter))
T = TextIter() # 创建实例对象.
# print(dir(T))
print(T) # TextIter类的实例对象具备__iter__则是可迭代对象.
print(callable(T)) # 注意这里是True
# for i in T: # 对可迭代对象进行遍历.
# print(i)
T1 = iter(T) # T1是迭代器对象.
# print(dir(T1)) # 迭代器对象. # 没有__call__方法.
print(T1)
print(callable(T1)) # 注意这里是False
# print(T1.__next__())
# print(T1.__next__())
# print(T1.__next__())
# print(T1.__next__()) # 运行到第四次则报错.
# for i in T1: # 对迭代器对象进行遍历.
# print(i)
T2 = iter(T, 3) # T必须是callable,否则无法返回callable_iterator
print(T2)
for i in T2:
print(i)
print('*'*20)
class MyIterable(object): # 可迭代对象.
def __init__(self, a):
self.a = a
self.b = [1, 2, 3]
self.c = iter(self.b)
def __iter__(self):
return MyIterator(self.a) # 返回迭代器对象.差不多返回MyIterator类的实例对象. My = MyIterator(self.a)
def __call__(self, *args, **kwargs):
ite = next(self.c)
return ite
class MyIterator(object): # 迭代器对象.
def __init__(self, abb):
self.abb = abb
self.app = 0
def __iter__(self): # 返回本实例对象.
return self
def __next__(self):
global x
x = self.app
while True:
self.app += 1
# try:
if self.app > self.abb:
raise StopIteration('抛出一个错误')
else:
return x
# except StopIteration:
# # break
# print('错误')
fn = MyIterable(5) # 创建MyIterable实例对象.
# print(dir(fn)) # 可迭代对象.
print(fn)
# print(list(fn))
# print(next(fn)) # 这里是一个错误问题,展示给你们看.记住fn是可迭代对象,不是迭代器对象.
# 然后我们先尝试可迭代对象的运用.
for i in fn: # for循环自带抛出错误后就停止
print(i)
# print(dir(iter(fn))) # 迭代器对象.
print(iter(fn)) # 可以先赋值给一个变量,然后运行迭代器next()方法.然后运行输出.
itt = iter(fn)
# print(dir(itt))
# print(itt.__call__())
# print(callable(itt)) # 不是一个可调用对象.
print(itt.__next__())
print(itt.__next__())
# print(itt.__next__())
# print(itt.__next__())
# print(itt.__next__())
# print(itt.__next__())
# for i in itt:
# print(i)
Itt = iter(fn, 3) # 返回一个callable_iterator对象.
print(Itt)
for i in Itt:
print(i)
print('*'*20)
class MyRange(object): # 实现和range()语句一样的效果.
def __init__(self, *params):
self.step = 1
# self.start = params[0] # 开始
# self.stop = params[1] # 结束
# self.step = params[2] # 步长
assert type(params) == tuple
if len(params) == 0:
raise TypeError('range参数不能为0')
if len(params) > 3:
raise TypeError('range参数只有3个')
assert len(params) >= 1 and len(params) <= 3
# 上面是上边界.
if len(params) == 1: # 一个参数的时候.
self.start = 0 # 默认起始为零
if params[0] <= 0:
self.stop = 0
else:
self.stop = params[0]
elif len(params) == 2: # 两个参数的时候.
# self.start = params[0] # 开始
# self.stop = params[1] # 结束
# if params[0] >= 0:
if params[0] < params[1]:
self.start = params[0]
self.stop = params[1]
else: # 让他返回一个空
self.stop = 0
self.start = 0
# else:
# self.start = params[0]
# self.stop = params[1]
else: # 传入三个参数开始、结束、步长.
assert len(params) == 3 # 确认传入的参数是3个.
if params[2] == 0: # range(0, 5, 1)
raise ValueError('range() arg 3 must not be zero')
elif (params[0] < params[1] and params[2] > 0) or (params[0] > params[1] and params[2] < 0):
self.start = params[0]
self.stop = params[1]
self.step = params[2]
else:
self.start = 0
self.stop = 0
self.start -= self.step
self.stop -= self.step
def __iter__(self):
return self # 返回当前实例对象.对象里面包含一些你对其实例对象进行的一些效果.
def __next__(self):
assert self.step != 0 # 步长不能为0.
if self.step > 0:
if self.start >= self.stop:
raise StopIteration
self.start += self.step
return self.start
else: # 步长小于0.
if self.start <= self.stop:
raise StopIteration
self.start += self.step
return self.start
print(list(range(5)))
print(list(MyRange(5)))
print('*'*20)
print(list(range(0, 5)))
print(list(MyRange(0, 5)))
print('*'*20)
print(list(range(-5, 5, 2)))
print(list(MyRange(-5, 5, 2)))
print('*'*20)
print(list(range(5, -5, -2)))
print(list(MyRange(5, -5, -2)))
# 生成器.
Str = '456'
Float = 1.0
Int = 1 # 可知可迭代对象.
print(isinstance(Str, Iterable), isinstance(Float, Iterable), isinstance(Int, Iterable))
List = []
Dict = {}
print(isinstance(List, Iterable), isinstance(Dict, Iterable)) # 列表和字典都是可迭代对象.
# 和下面是一样的,只是为了了解清楚怎么运行的.
# yield_list = [1, [4, 5], [[8]], [7, 8, 9], 10]
#
#
# def flatten(n):
# try:
# for i1 in n:
# # print(i1)
# for ii in flatten(i1): # [4, 5]
# # print(ii)
# yield ii
# except TypeError:
# yield n
#
#
# f = flatten(yield_list)
# print(list(f))
# # for i in f:
# # print(i)
# 用于展平列表元素.
def yield_i(n):
# print(n)
try:
for i1 in n: # 或者MyRange().[3, 4]
# yield 'PP ' + str(i)
# print(i1) # 3或4
# print(yield_i(i1))
for ii in yield_i(i1):
# print(ii)
yield ii
except TypeError:
yield n
y = yield_i([1, 2, [3, 4], [[5]]])
print(list(y))
# for i in y:
# print(i)
# 上面内容只能应用于整型或者浮点型等不可迭代对象.如果在列表元素当中夹杂了字符串(可迭代对象),则会报错.
# 上面内容有整型的报错而终止循环,但是字符串(可迭代对象)则不会终止循环.
# 为了解决字符串等可迭代问题.我们可以加一个判断语句.
def yield_ii(n):
try:
for i1 in n:
if isinstance(i1, Iterable) and not isinstance(i1, list): # 判断i1是否是可迭代对象.
yield '<可迭代对象> 类型:' + str(type(i1))
else:
for ii in yield_ii(i1):
yield ii
except TypeError:
yield n # 解决列表的展平问题,如果到不可迭代对象后,则会抛出错误,在用生成器返回,进行遍历,遍历后,再次进行生成器.返回生成器对象.
y2 = yield_ii([1, 2, [3, 4], [[5]], 'String', [6], 'Str'])
for i in y2:
print(i)
# 下面还有一些例子:
from itertools import count, cycle, islice
counter = count(start=13)
print(next(counter))
print(counter.__next__())
print('*'*20)
colors = cycle(['red', 'white', 'blue'])
print(next(colors))
print(next(colors))
print(colors.__next__())
print(colors.__next__())
print('*'*20)
limited = islice(colors, 0, 4)
# print(dir(limited))
print(list(limited))
print('*'*20, '字典环节', '*'*20)
brand = ['开始', '结束', '步长']
slogan = ['0', '5', '2']
print('联系:', brand[slogan.index('5')])
ZiDian = {'开始': '0', '结束': '5', '步长': '2'}
print(ZiDian.keys()) # 键名.
print(ZiDian.values()) # 值.
print(ZiDian.items()) # 键值.
# get()方法提供了更宽松的方式去访问字典项,当键不存在的时候,get()方法并不会报错,只是默默第返回一个None,表示啥都没找到.
print(ZiDian.get('开始'))
print(ZiDian.get('无', '木有'))
# copy()方法是复制字典(全拷贝)
brand1 = brand.copy() # 对于列表的复制copy.
print(brand, id(brand))
print(brand1, id(brand1))
ZiDian1 = ZiDian.copy() # 对于字典的复制copy.
print(ZiDian, id(ZiDian))
print(ZiDian1, id(ZiDian1))
ZiDian1['开始'] = '2'
print(ZiDian, ZiDian1)
# pop()是给定键弹出对应的值,popitem()是随机弹出一个项.
print(ZiDian1.pop('步长'))
print(ZiDian1)
print(ZiDian1.popitem())
print(ZiDian1)
# setdefault()方法与get()方法相似,但setdefault()在字典中找不到相应的键值时会自动添加.
print(ZiDian1.setdefault('步长', '2'))
print(ZiDian1)
# update()方法可以更新字典.
print(ZiDian1.update({'range': 'MyRange'}))
print(ZiDian1)
print(ZiDian1.update({'range': 'Range'}))
print(ZiDian1)
# clear()可清空一个字典.
print(ZiDian1.clear())
print(ZiDian1)
print('*'*20, '字典环节', '*'*20)
print('*'*20, '集合环节', '*'*20)
# 集合中的元素都是唯一的(集合会自动帮我们把重复的数据清理掉,集合是无序的,所以不能试图去索引集合中的某一个元素).
num = {'1': '0'}
print(type(num))
num1 = {'1', 1, '2', 2}
print(type(num1))
# print(dir(num1))
print(num1)
# 使用add()方法可以为集合添加元素,使用remove()方法可以删除集合中已知的元素.
# 不可变集合(把元素给froze冰冻起来)(像元组一样不能随意地增加或删除集合中的元素).
print('*'*20, '集合环节', '*'*20)
import pickle # 可以非常容易地将列表、字典这类复杂的数据类型存储为文件.(转化成二进制).
my_list = ['1', 5, '8', 9]
print(pickle.dumps(my_list))
print(pickle.loads(b'\x80\x03]q\x00(X\x01\x00\x00\x001q\x01K\x05X\x01\x00\x00\x008q\x02K\te.')) # 注意:是字节类型.
import easygui # EasyGui
# print(easygui.msgbox('嗨,python'))
# from easygui import *
# print(msgbox('嗨, python'))
# import easygui as f
# print(f.msgbox('嗨,python'))
# # 显示图片(注:图片需要为GIF格式,且存放在python.exe通目录).
print('*'*20, '下面简单说下类', '*'*20)
# 组合(将需要的类一起进行实例化并放入新的类中)这部分会在下面运行当中呈现出来效果.
class Person(object):
name = 'Person' # 类方法.
__name = '私有Person' # 私有方法.
def __init__(self, a, b):
self.a = a
self.b = b
self.num = 5
self.flag = True
print('Person __init__方法.')
def pen(self):
return self.__name # 从内部进行把私有名给输出来.
def time(self):
if self.flag:
print('前 %s 小时' % self.a)
self.flag = False
else:
print('后 %s 小时' % self.b)
self.flag = True
p = Person(12, 12) # 创建实例对象.
print(id(p)) # p 和 p1 id不一样,一个类可以创建多个对象,这就是多态.
p1 = Person(6, 6)
print(id(p1))
print(p1.name)
# print(p.__name) # 会报错,这是私有类方法,不能被输出.
print(p1.pen()) # 可以通过访问类里面的方法进行内部的反馈.
# print(p1._Person__name) # 在python中,只是把私有类方法改了下名字而已.
class Person1(Person): # 应用于继承.
pass
print('*'*20, 'Person1环节')
p2 = Person1(12, 12)
p2.time() # 类的继承,子类可以应用父类方法.
p2.time()
print(p2.pen())
class Person2(Person):
def __init__(self, c): # # 注意,如果子类有和父类一样的实例方法或类方法,会进行覆盖.
self.c = c
self.g = Person(12, 12) # 类似 f = Person(d)实例化得到对象.
Person.__init__(self, 12, 12) # 第一种方法解决覆盖问题. # 第一种方法比如我修改了父类,后面也需要修改,造成不必要的麻烦.# 注意:此处
# self参数依旧是指向子类Person2的指针.通俗点,就是我把Person类的__init__方法指向了Person2,其实self是Person2的实例化对象.
# 意思就是我把父类方法指向了Person2的实例化对象.
# super(Person2, self).__init__(12, 12) # 第二种方法解决覆盖问题.
def eat(self):
if self.c == 12:
print('当前时间 %s ' % self.c)
self.c = 24
else:
print('当前时间 %s ' % self.c)
self.c = 12
print('*'*20, 'Person2环节')
p3 = Person2(12) # 创建实例化对象.
p3.eat()
p3.eat()
p3.time() # 注意,如果子类有和父类一样的实例方法或类方法,会进行覆盖. # 为了解决错误问题.需要导入父类的__init__方法.
p3.time()
# 也可以多继承,一个子类继承多个父类,就是你可以有多个爹,对吧?大致意思是class Person1(Person, Person2) # 多继承在应用方法上,有顺序之分
# 顺序的话基本不用你去算了,你只需要认定,第一个输入的参数就是第一个顺序.
print('*'*20, '组合')
per = Person2(12) # 进行实例化对象
print(per.g.num)
# 以下例子可见,对实例对象c的count属性赋值后,就相当于覆盖了类对象C的count属性。如果没有赋值覆盖,那么引用的是类对象的count属性
p4 = Person(12, 12) # 创建实例化对象.
p5 = Person(12, 12)
p6 = Person(12, 12)
print(id(p4), id(p5), id(p6))
print(p4.name, p5.name, p6.name)
p6.name = 'Hello Person'
print(p4.name, p5.name, p6.name)
Person.name = '<Person>'
print(p4.name, p5.name, p6.name)
# 另外,如果属性的名字跟方法名相同,属性会覆盖方法.
class C(object):
def method(self):
print('C:xxx')
c = C() # 实例化对象.
c.method()
c.method = 1
print(c.method)
# c.method() # 会报错,可见,方法x()已经被属性method给覆盖了.
# 结论:不要试图在一个类里边定义出所有能想到的特性和方法,应该利用继承和组合机制来进行扩展;
# 用不同的词性命名,如属性名用名词、方法名用动词,并使用骆驼命名法等。
print('*'*20, '下面是绑定的概念.')
# (python严格要求需要有实例才能被调用,即绑定概念)
class B(object):
def printB():
print('no zuo no die')
B.printB() # 没有绑定实例对象时.
b = B()
# b.printB() # 出现错误原因是由于绑定机制,自动把b对象作为第一个参数传入.
class A(object):
name = '123'
def printA(self): # 我方法绑定给实例对象.
print('A')
def printAA(self):
self.printA()
a = A()
a.printA()
a.printAA()
# Python严格要求方法需要有实例才能被调用,这种限制其实就是Python所谓的绑定概念.
# issubclass(class, classinfo) 如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回True,否则返回False.
print(issubclass(A, object))
# isinstance(object, classinfo) 如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回True,否则返回False.
print(isinstance(a, A))
print(isinstance(a, object))
# hasattr(object, name) 用来测试一个对象里是否有指定的属性,第一个参数(object)是对象,第二个参数(name)是属性名(属性的字符串名字).
print(hasattr(a, 'name'))
# getattr(object, name[, default]) 返回对象指定的属性值,如果指定的属性不存在,则返回default(可选参数);若没有设置default参数,则抛出异常.
print(getattr(a, 'age', '20'))
# setattr(object, name, value) 可以设置对象中指定属性的值,如果指定的属性不存在,则会新建属性并赋值.
setattr(a, 'age', '20')
print(getattr(a, 'age'))
# delattr(object, name) 用于删除对象中指定的属性,如果属性不存在,抛出异常。
print(delattr(a, 'age'))
print(getattr(a, 'age', 50))
# property(fget=None, fset=None, fdel=None, doc=None)
# 用来通过属性设置属性,第一个参数是获取属性的方法名,第二个参数是设置属性的方法名,第三个参数是删除属性的方法名.
print('*'*20)
class D(object):
def __init__(self, size=10):
self.size = size
def getsize(self):
return self.size
def setsize(self, value):
self.size = value
def delsize(self):
del self.size
x = property(getsize, setsize, delsize)
d = D()
print(d.x)
d.x = 12
print(d.x)
del d.x
# print(d.x) # 会报错.
print('*'*20, '魔术方法')
# 注:__init__()方法的返回值一定是None .
# 其实,__new__()才是在一个对象实例化时候所调用的第一个方法,它的第一个参数是这个类(cla),而其他的参数会直接传递给__init__()方法.
class CapStr(str):
def __new__(cls, string):
string = string.upper() # 大写
return str.__new__(cls, string) # 使用str的__new__方法,指向当前类,并把值提交给str.
a = CapStr('hello world')
print(a)
# __del__(self) 当对象将要被销毁的时候,这个方法就会被调用。但要注意,
# 并非del x就相当于调用x.__del__(),__del__()方法是当垃圾回收机制回收这个对象的时候才调用的。
class Poo1(object):
def __init__(self):
print('__init__被调用')
# def __del__(self):
# print('__del__被调用')
k = Poo1()
k1 = k
k2 = k1
# print(id(k)) # 多指向标签.
# print(id(k1))
# print(id(k2))
# del k
# del k1
# del k2
print('*'*20)
class NewInt(int):
def __init__(self, value):
self.value = value
def __add__(self, other): # 先说参数,第一个self参数是当前实例化参数,而other是另外一个实例化参数.
print(id(self), id(other)) # 进行比较id实例化a、b,应该和我猜想的一样吧,相当于我把实例化的b当成参数了.
# print('add', self, other)
# return int.__sub__(self, other) # 可以尝试着改成 int.__add__(self, other)
# print(self.value, other.value) # 为了进一步验证我的想法.
return int(self) + int(other) # #将self与other强制转换为整型,所以不会出现两个对象相加触发__add__()方法
def __sub__(self, other):
# print('sub', self, other)
# return int.__add__(self, other) # 和上面一样进行修改.
return int(self) - int(other)
# def __str__(self):
# return self.value
a = NewInt(3)
b = NewInt(5)
c = NewInt(1)
# print(a, b)
# print(a.value)
# print(b.value)
# print(type(a), type(b)) # 先说下相加和相减的前提是类型要一样,从这里可以看出,出自同一个类.
print(id(a), id(b))
# print(a) # out -> 3
# print(b) # out -> 5
print(a + b) # 两个对象相加,触发 __add__(self,other)方法.# 顺序>>实例a -> 触发add方法(+) -> 实例b. + 返回 - 的效果.
# a + b运行模式应该是,b 进入了 a中,所以当前self是a,所以b相当于传入进去的参数,但是a和b都是同一个类.所以a能用的b也能用.
print(a - b)
print(a + b + c)
class NenInt(object):
def __init__(self, value):
self.value = value
# print('__init__ %s ' % self.value) # 体现是否创建了实例化对象.
def __add__(self, other):
# NenInt(f'{self.value}{other.value}') 相当于一个实例化对象.NenInt('aaaAAA').
# print('add', self, other)
return NenInt(f'{self.value}{other.value}') # 运行顺序 -> 先运行Nen + Nen1,运行完之后(Nen + Nen1) + Nen2.
def __str__(self): # 对实例化对象进行返回self.value.
return self.value
NenInt('ooo')
Nen = NenInt('aaa')
Nen1 = NenInt('AAA')
Nen2 = NenInt('bbb')
# Nen3 = NenInt('BBB') # 用于验证.
# print(Nen)
print(Nen + Nen1 + Nen2) # 可以把__str__方法注释掉,看下前后效果.
class Vector(object):
def __init__(self, box, eye):
self.box = box
self.eye = eye
def __add__(self, other):
return Vector(self.box + self.eye + other.box, self.eye + other.box + other.eye)
def __str__(self):
return 'Vector ( %s , %s )' % (self.box, self.eye)
v = Vector(10, 2)
v1 = Vector(20, -5)
print(v + v1)
print('*'*20)
# 这里a是加数,b是被加数,如果a对象的__add__()方法没有实现或者不支持相应的操作,那么python就会自动调用b的__radd__()方法
class NInt(int):
def __init__(self, q):
self.q = q
def __radd__(self, other):
# print(self.q) # 用于观看self实例化对象是谁.
return int.__sub__(self, other) # 调用减.
a = NInt(5)
b = NInt(3)
print(a + b) # 由于a对象默认有__add__()方法,所以b的__radd__()没有执行.
print(3 + b) # 由于3无__add__()方法,所以执行b的反运算__radd__(self,other)方法,其中self是b对象.
print(b + 3)
print('*'*20)
# class MyClass(object):
# def __add__(self, other):
# return self + other
#
# # def __str__(self):
# # return self
#
#
# Cla = MyClass()
# Cla1 = MyClass()
# print(Cla + Cla1)
from datetime import datetime
# 定制一个计时器类.
# class MyTimer(object):
# def __init__(self, total=0):
# self.begin = 0 # 时间始.
# self.end = 0 # 时间末.
# self.total = total
#
# def __add__(self, other):
# # return '相加 %s 秒' % round(float(self.total) + float(other.total), 1) # 本身就是浮点数.
# return MyTimer(self.total + other.total)
#
# def __str__(self): # 用于解决实例对象的返回的问题.
# return str(self.total)
#
# def start(self): # 启动计数.
# print('启动计时器...')
# self.begin = datetime.now() # 标记起始时间.
# return self.begin
#
# def stop(self): # 停止计时.
# print('终止计时器!!!')
# self.end = datetime.now()
# self.total = round(self.end.timestamp() - self.begin.timestamp(), 1)
# print('总共运行了 %s 秒' % self.total)
# return self.total
#
# def cycle(self):
# name = input('start/stop:').strip()
# while True:
# if name == 'start':
# self.start()
# name = input('stop:').strip()
# if name == 'stop':
# pass
# elif name == '0':
# break
# else:
# print('*' * 20, '请按照规则:start/stop或者退出(0)', '*' * 20)
# elif name == 'stop':
# self.stop()
# break
# # elif self.name == '+': # 本来也可以在这里加,但是针对性太强,反而没有灵活性的去相加.
# # pass
# else:
# break
#
#
# time = MyTimer()
# # print(time.start())
# # print(time.stop())
# time1 = MyTimer()
# time2 = MyTimer()
# time.cycle()
# time1.cycle()
# time2.cycle()
# # time2 = MyTimer()
# print('相加', time + time1 + time2, '秒')
# # print(time + time1)
# class MyTimer(int):
# def __init__(self, total=0):
# self.begin = 0 # 时间始.
# self.end = 0 # 时间末.
# self.total = total
#
# def __add__(self, other):
# # print(type(self), type(other)) # <class '__main__.MyTimer'>
# # print(self, other)
# # print(self.total, other.total)
# # print(type(self), type(other))
# print(self, other, type(self), type(other), type(int(self)), type(int(other)))
# return int(self) + int(other)
# # return float(self) + float(other) # 本身就是浮点数.
# # return '相加 %s 秒' % MyTimer(self.total)
#
# def __radd__(self, other):
# print('__radd__')
# return int.__add__(self, other)
#
# # def __str__(self): # 用于解决实例对象的返回的问题.
# # return str(self.total)
#
# def start(self): # 启动计数.
# print('启动计时器...')
# self.begin = datetime.now() # 标记起始时间.
# return self.begin
#
# def stop(self): # 停止计时.
# print('终止计时器!!!')
# self.end = datetime.now()
# self.total = round(self.end.timestamp() - self.begin.timestamp(), 1)
# print('总共运行了 %s 秒' % self.total)
# # return self
#
# def cycle(self):
# name = input('start/stop:').strip()
# while True:
# if name == 'start':
# self.start()
# name = input('stop:').strip()
# if name == 'stop':
# pass
# elif name == '0':
# break
# else:
# print('*' * 20, '请按照规则:start/stop或者退出(0)', '*' * 20)
# elif name == 'stop':
# self.stop()
# break
# # elif self.name == '+': # 本来也可以在这里加,但是针对性太强,反而没有灵活性的去相加.
# # pass
# else:
# break
#
#
# time = MyTimer(5)
# # print(time.start())
# # print(time.stop())
# time1 = MyTimer(2)
# time2 = MyTimer(1)
# time3 = MyTimer(1)
# # time.cycle()
# # time1.cycle()
# # time2.cycle()
# print(time + time1 + time2 + time3) # 从上面种种表现可知,我是先触发__add__然后再触发了__radd__.
# # print(time + time1)
# print(time2)
# print(type(time2))
# class MyTimer(object):
# def __init__(self, total=0):
# self.begin = 0 # 时间始.
# self.end = 0 # 时间末.
# self.total = total
#
# def __add__(self, other):
# # print(self, other, type(self), type(other))
# # print('__add__')
# try:
# return str(self.total + other.total)
# except AttributeError:
# return self.total + other
#
# def __radd__(self, other):
# # print('__radd__')
# return MyTimer.__add__(self, float(other))
#
# # def __str__(self): # 用于解决实例对象的返回的问题.
# # return str(self.total)
#
# def start(self): # 启动计数.
# print('启动计时器...')
# self.begin = datetime.now() # 标记起始时间.
# return self.begin
#
# def stop(self): # 停止计时.
# print('终止计时器!!!')
# self.end = datetime.now()
# self.total = round(self.end.timestamp() - self.begin.timestamp(), 1)
# print('总共运行了 %s 秒' % self.total)
# # return self
#
# def cycle(self):
# name = input('start/stop:').strip()
# while True:
# if name == 'start':
# self.start()
# name = input('stop:').strip()
# if name == 'stop':
# pass
# elif name == '0':
# break
# else:
# print('*' * 20, '请按照规则:start/stop或者退出(0)', '*' * 20)
# elif name == 'stop':
# self.stop()
# break
# else:
# break
#
#
# time = MyTimer()
# # print(time.start())
# # print(time.stop())
# time1 = MyTimer()
# time2 = MyTimer()
# # time3 = MyTimer()
# time.cycle()
# time1.cycle()
# time2.cycle()
# # time3.cycle()
# print('总共', time + time1 + time2, '秒') # 从上面种种表现可知,我是先触发__add__然后再触发了__radd__.
# # print(time + time1)
# # print(time2)
# # print(type(time2))
# class MyTimer(object): # 之后再尝试了.
# def __init__(self):
# self.date = ['年', '月', '日', '小时', '分钟', '秒']
# self.begin = 0
# self.end = 0
#
# def __add__(self, other):
# return None
#
# def start(self):
# if not self.stop:
#
print('*'*20)
class IndexAtt(object):
# x = 1
def __getattribute__(self, item): # –定义当该类的属性被访问时的行为.
print('__getattribute__')
return super(IndexAtt, self).__getattribute__(item) # 根类__getattribute__应该返回给根类的__getattr__.
# return IndexAtt.__getattr__(self, item)
def __getattr__(self, item): # –定义当用户试图获取一个不存在的属性时的行为.
print('__getattr__')
return ' %s 类方法不存在.' % item
def __delattr__(self, item): # –定义当一个属性被删除时的行为.
print('__delattr__')
super(IndexAtt, self).__delattr__(item)
def __setattr__(self, key, value): # –定义当一个属性被设置时的行为.
print('__setattr__')
super(IndexAtt, self).__setattr__(key, value)
def __str__(self):
return 'I'
I = IndexAtt()
print(I.x)
print('*'*20)
I.x = 2
print('*'*20)
print(I.x)
print('*'*20)
del I.x
print('*'*20)
print(I.x)
print('*'*20)
class Rectangle(object):
def __init__(self, width, height):
self.width = width # 宽.
self.height = height # 高.
def __setattr__(self, key, value):
if key == 'square':
self.width = value
self.height = value
else:
self.__dict__[key] = value
def getarea(self):
return self.width * self.height
r = Rectangle(5, 4)
print(r.getarea())
r.square = 5
print(r.getarea())
r.p = 4
print(r.__dict__)
print('*'*20)
# 描述符.
class MyDescriptor(object):
def __init__(self):
self.a1 = 'aa1'
print('MyDescriptor')
def __get__(self, instance, owner):
print('get', self, instance, owner)
return self
def __set__(self, instance, value):
print('set', self, instance, value)
def __delete__(self, instance):
print('del', self, instance)
def __getattribute__(self, item):
# print(self, item)
# return '触发1 %s ' % item
return super(MyDescriptor, self).__getattribute__(item)
class Test(object):
x = MyDescriptor() # 取MyDescriptor类的实例指派给Test类的属性x. # 相当于创建实例对象.
def __init__(self):
self.a2 = 'a2'
self.x = '实例化对象' # 类似Test实例化对象对x类方法进行设置.
print('Test')
# def __getattribute__(self, item): # 刻属性可以让描述器失效.
# return '触发2 %s ' % item
# return super(Test, self).__getattribute__(item)
test = Test()
test.x
Test.x
print(Test.x.a1)
# print(test.x.a1)
# print(test.x) # 有顺序之分.__getattribute__ -> 数据描述符 -> 实例对象的字典 -> 类的字典 -> 非数据描述符 -> 父类的字典 -> getattr().
# 所以呐,就先注释掉__set__、__get__、__delete__其中两个使之变成非数据描述符.
# test.x = '可口'
# del test.x版权声明:本文为m0_55990042原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。