Python学习日志10.10

昨日内容

继承

1.什么是继承?

继承就是新建类的一种方式,新建出来的类是子类,被继承的类就是父类

子类可以继承父类的所有属性和方法

2.为什么要继承?

继承解决了类与类之间冗余的问题

3.怎么使用继承?

经典类:默认情况下没有继承object类

新式类:默认情况下继承object类

Python3中都是新式类,默认情况下继承了object

class People():
    school = 'Sh'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        
        
class Student(People):
    def __init__(self, name, age, gender, course):
        People.__init__(self, name, age, gender)
        self.course = course
        
class Teacher(People):
    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        self.level = level

继承下的属性查找

单继承下的属性查找

查找顺序:先从对象自己的名称空间中查找,然后去产生这个对象的类中查找,然后再去继承的父类中查找,如果都找不到,那就报错。但是在任何一个环节中查找到了,那就不在往下继续查找了

多继承下的属性查找

菱形查找:

经典类:按照深度优先查询

新式类:按照广度优先查询

在python3中都是新式类,就是广度优先查询

非菱形查找:就是按照每个继承类的分支挨个往下找

super关键字和mro列表

class People():
    school = 'Sh'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        
        
class Student():
    def __init__(self, name, age, gender, course):
        People.__init__(self, name, age, gender) # 指名道姓的调用
        # super()返回的就是一个对象
        super(Student, self).__init__(name, age, gender)
        super().__init__(name, age, gender) # 也是使用最多的
        self.course = course
        
class Teacher(People):
    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        super(Student, self).__init__(name, age, gender)
        super().__init__(name, age, gender) # 也是使用最多的
        self.level = level

 mro列表是子类继承的所有父类合并后通过c3算法得出来的查找顺序列表

print(C.mro()) # 列表
print(C.__mro__) # 元组

多态

面向对象的三大特征

同一种事物的多种形态

抽象类:在父类中限制子类的行为,父类中限制子类必须有某个方法,没有就报错

抽象类中父类的方法不是为了实现功能,也不是实现核心逻辑,而是为了限制子类的行为

import abc

class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):pass

	@abc.abstractmethod
    def speak1(self):pass

"""以后但凡继承Animal类的子类中都必须有speak功能,抽象类不能够实例化,只能够被继承"""
class People(Animal):
    def speak(self):
        pass
    def speak1(self):
        pass

 python更崇尚鸭子类型:更加关注的是对象的行为,而不关注类型

class People():
    def speak(self):
        pass
class Dog():
    def speak(self):
        pass  
obj=People()
obj1=Dog()
def animal(obj):
    return obj.speak()

animal(obj)
animal(obj1)

len('hello')
len([1,2,3,4])

def len(item):
    return item.__len__
len(123)

 多态的特性:在不考虑对象类型的情况下,直接调用对象的方法或者属性

今日内容

组合

什么是组合?

组合就是,一个对象拥有一个属性,该属性的值是另一个对象

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

class Bar():
    def __init__(self, n):
        self.n = n

"""一个对象拥有一个属性,该属性的值是另外一个对象."""
obj=Bar(10)
obj1 = Foo(20)
# 超级对象,通过一个属性可以访问到另外一个对象的值
obj.x=obj1

print(obj.x.m)    

 什么场景下使用继承?什么场景下使用组合?

继承:什么是什么

组合:什么有什么

class People():
    school = 'SH'

    def __init__(self, name, age, gender, course_name=None, course_price=None, course_period=None):
        self.name = name
        self.age = age
        self.gender = gender
        self.course_name = course_name
        self.course_price = course_price
        self.course_period = course_period
class Admin(People):
    def __init__(self, name, age, gender):
        super().__init__(name, age, gender)

class Course():
    def __init__(self, name, price, period):
        self.name = name
        self.price = price
        self.period = period


python=Course('python', 10000, '6mon')
linux=Course('linux', 20000, '5mon')
# print(python.name)
# print(python.price)
# print(python.period)

class Student(People):
    def __init__(self, name, age, gender, course=None):
        super().__init__(name, age, gender)
        if course is None:
            course = []
        self.course = course


stu = Student('kevin', 20, 'male')
stu.course.append(python.name)
stu.course.append(linux.name)
print(stu.course) # [<__main__.Course object at 0x000001F258F86B80>, <__main__.Course object at 0x000001F258F511C0>]
# stu.course: []
for i in stu.course:
    print(i)

class Teacher(People):
    def __init__(self, name, age, gender, level):
        super().__init__(name, age, gender)
        self.level = level


tea = Teacher('ly', 19, 'female', 10)
print(tea.course_name)
tea.course=linux

print(tea.course.name)
print(tea.course.price)

反射

在python中,反射指的是通过字符串来操作对象的属性,涉及到四个内置函数的使用(python中一届皆为对象,类和对象都可以使用下述的四个方法)

四个内置函数:

getattr:获取属性

setattr:设置属性

hasattr:判断是否有某个属性

delattr:删除

class Student():
    school = 'SH'

    def __init__(self,name, age):
        self.name=name
        self.age = age

    def func(self):
        print('from func')

    def index(self):
        print('from index')
stu = Student('kevin', 20)
# attr=input('请输入你要操作的属性名:')
# print(stu.school)
# print(stu."school")
"""反射:就是通过字符串的形式来操作对象的属性"""
# 1. 获取属性
"""当你查询的属性不存在的时候,如果给了第三个参数,就返回第三个参数"""
# res=getattr(stu, 'school1', 666) # SH 666

"""如果你给了第三个参数,查询的属性也存在,那就直接返回属性对应的值,默认值就没用了"""
# res=getattr(stu, 'school', 666) # SH 666
# res1=getattr(stu, 'name') # SH
# res2=getattr(stu, 'age') # SH
# print(res,res1, res2)
# print(stu.school)
# print(res)


### 函数的用法
"""必须掌握!!!!!!"""
# res=getattr(stu, 'func1', stu.index) #### 用的是最多的
# print(res) # <bound method Student.func of <__main__.Student object at 0x000001963F5C5A60>>
# res()

### 设置
# setattr(stu, 'x', 666) # stu.x=666
# print(stu.__dict__)


### hasattr
print(hasattr(stu, 'func'))
if hasattr(stu, 'func'):
    getattr(stu, 'func')()
else:
    ...

### delattr
# delattr(stu, 'name')
# del stu.name
# print(stu.__dict__)

# import time
# time=__import__('time') # import time
# print(time.time())

random=__import__('random')
print(random.randint(0,8))

内置方法之魔术方式

双下划线开头,满足一定条件就会触发

1.__init__

2.__str__,__repr__

   """
        1. 打印对象的时候,输出对象的时候会自动触发类中得__str__方法
        2. 返回值必须是字符串形式
        3. 如果它跟__repr__方法同时存在,__str__的优先级更高
    """
    def __str__(self): # 这个用的是最多的
        print('str')
        return 'from str'

    def __repr__(self):
        print('repr')
        return 'from repr'

stu = Student('ly', 20)
# print(stu) # <__main__.Student object at 0x00000226AC4F5A60>

# print('repr:', repr(stu))
print('str:', str(stu))

class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.f = open('a.txt', 'w')
    """
    1.当你删除对象的时候会触发__del__的执行
    2. 当整个脚本的程序都执行完毕的时候,也会触发__del__的执行
    3. 一般用在用来在对象被删除时自动触发回收系统资源的操作
    """
    def __del__(self):
        print('from _del')
        self.f.close()


mysql = MySQL('127.0.0.1', 3306)

print('1223')
print('1223')
print('1223')
print('1223')
print('1223')

print(isinstance(123, str))
print(type(123) is int)
class Foo:
    pass
class Bar(Foo):
    pass
class Bar1():
    pass
print(issubclass(Bar1, Foo))


class Foo:
    """
    '我是描述信息asdasd'
    '我是描述信息asdasd'
    '我是描述信息asdasd'
    """

    pass
class Bar(Foo):
    pass
print(Bar.__doc__)

__enter__和__exit__

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

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
        # return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')

"""with它可以用在很多地方,但是,出现with语句后面的对象中得类必须要声明__enter__和__exit__"""

with Open('a.txt') as f:
    print('=====>执行代码块')
    print('=====>执行代码块')
    print('=====>执行代码块')
    print('=====>执行代码块')
    print('=====>执行代码块')
    # print(f,f.name)
    
简答题:先聊聊with 的用法? 问with上下文管理协议的执行原理? 为什么打开文件只会可以自动关闭?请说出原因


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

    def __enter__(self):
        print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
        # return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with中代码块执行完毕时执行我啊')
        print(exc_type) # 异常类型
        print(exc_val) # 异常值
        print(exc_tb) # 追溯信息
        return True # 如果你在这个方法里面返回了True,with代码块中出现了异常,就相当于没有出现异常

"""with它可以用在很多地方,但是,出现with语句后面的对象中得类必须要声明__enter__和__exit__"""

# with Open('a.txt') as f:
#     print('=====>执行代码块')
#     print('=====>执行代码块')
#     print('=====>执行代码块')
#     print('=====>执行代码块')
#     print('=====>执行代码块')
#     # print(f,f.name)
"""如果with代码块中出现了异常,则with语句之后的代码都不能正常执行"""
with Open('a.txt') as f:
    print('=====>执行代码块')
    raise AttributeError('***着火啦,救火啊***') # 抛出异常,主动报错
print('0'*100) #------------------------------->不会执行

__setattr__,__delattr__,__getattr__

__setattr__,__delattr__,__getattr__

class Foo:
    x=1
    def __init__(self,y):
        self.y=y

    """当你找的属性不存在的时候,会触发__getattr__,但是必须是点语法的时候才会"""
    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')


    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value # self.a=20
        # self.key=value #这就无限递归了,你好好想想
        self.__dict__[key]=value #应该使用它


    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #无限递归了
        self.__dict__.pop(item)

obj=Foo(10)
# obj.z
obj.a=20
print(obj.a)

del obj.a

__setitem__,__getitem__,__delitem__

__setitem__,__getitem,__delitem__

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

    """当你通过中括号获取对象的属性的时候,会自动触发__getitem__"""
    def __getitem__(self, item):
        print('__getitem__')
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        # key:age
        # value:18
        print('__setitem__')
        self.__dict__[key] = value
        #  self.__dict__['age'] = 18

    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
        pass

    # def __delattr__(self, item):
    #     print('del obj.key时,我执行')
    #     self.__dict__.pop(item)
obj=Foo('tom')
# print(obj.name)

# obj['name']
obj['age'] = 18
# obj.age=18
print(obj.age)

del obj['age']

__call__

class Foo:

    def __init__(self):
        pass
    #### 当对象加括号的时候会触发__call__的执行
    def __call__(self, *args, **kwargs):
        print('__call__')


obj=Foo()
print(obj)
obj()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值