python基础学习

# -*- 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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值