3.26

3.26

对象属性的增删改查

class Student:
    def __init__(self, name, gender='男', age=18, tel=''):
        self.name = name
        self.gender = gender
        self.age = age
        self.tel = tel

    def __repr__(self):
        return str(self.__dict__)
    
    
stu1 = Student('小明', '男', 18, '110') 

1.查 - 获取属性的值
对象.属性 - 获取执行属性对应的值,如果属性不存在报错
getattr(对象, 属性名) - 获取执行属性对应的值,如果属性不存在报错
getattr(对象, 属性名, 默认值) - 获取执行属性对应的值,如果属性不存在不报错,直接返回指定的默认值

print(stu1.name)
print(getattr(stu1, 'name'))

# 方法二可以动态确定需要获取的内容
# value = input('学生的哪个信息: name? age? tel? gender?:')
# # print(stu1.value)
# print(getattr(stu1, value))

# print(stu1.score)    # AttributeError: 'Student' object has no attribute 'score'
print(getattr(stu1, 'score', 0))     # 设置默认值,在没有的时候返回

2.增、改
对象.属性 = 值 - 如果属性存在就是修改,属性不存在就是添加
setattr(对象, 属性名, 值) - 如果属性存在就是修改,属性不存在就是添加

stu1.name = '小花'
print(stu1)

stu1.score = 100
print(stu1, stu1.score)

setattr(stu1, 'height', 170)
print(stu1)

setattr(stu1, 'age', 30)
print(stu1)

3.删
del 对象.属性
delattr(对象, 属性名)

del stu1.gender
print(stu1)
# print(stu1.gender)  # AttributeError: 'Student' object has no attribute 'gender'

delattr(stu1, 'tel')
print(stu1)

内置属性

class A:
    x = 10

    def __init__(self, m=10, n='hello', p=True):
        self.m = m
        self.n = n
        self.p = p
        self.name = '小花'

    def f1(self):
        print(f'对象方法: {self.m}')

    @classmethod
    def f2(cls):
        print(f'类方法:{cls.x}')

    @staticmethod
    def f3():
        print('静态方法')


a = A()

1.内置属性 - 创建类的时候系统自动添加的属性就是内置属性
1)_dict_
类.__dict__ - 将类转换成字典,将所有的类属性名作为键,类属性对应的值作为值
对象.__dict__ - 将对象转换成字典,对象属性名是键,对象属性对应的值是值

print(A.__dict__)
print(a.__dict__)       # {'m': 10, 'n': 'hello', 'p': True}

2.__class__
对象.__class__ - 获取对象对应的类,功能和type一样

print(a.__class__, type(a))

3.__name__
类.__name__ - 获取类名

print(A.__name__)    # 'A'

4.__doc__
类.__doc__ - 获取类的说明文档

print(int.__doc__)

5._module_
类.__module__ - 获取定义指定类的模块名

print(A.__module__, int.__module__)

类._base_ - 获取当前类的父类
类.__bases__ - 获取当前类所有的父类

print(A.__base__)   # <class 'object'>
print(A.__bases__)  # (<class 'object'>,)
class Student:
    # 类属性__slots__是用来约束当前类的对象最多有哪些对象属性;
    # 注意:如果给类的__slots__属性赋值了,那么这个类的对象就不能再使用__dict__属性
    __slots__ = ('name', 'age', 'score', 'height')

    def __init__(self):
        self.name = '小明'
        pass


stu = Student()
print(stu.name)

stu.age = 18
print(stu.age)

# stu.nme = '小花'

私有化

1.访问权限(面向对语言通用)

公开的:属性和方法在类的内部、类的外部都可以使用,也可以被继承 (python中所有的属性和方法都是公开的)
保护的:属性和方法在类的内部可以使用,也可以被继承
私有的:属性和方法只能在类的内部使用

2.python私有化是假的: 在名字前加__

class A:
    num = 18
    __x = 20

    def __init__(self):
        self.__name = '小明'

    def f1(self):
        print(A.num)

    @classmethod
    def f2(cls):
        print('内部:', A.__x)
        A.__f3()

    @staticmethod
    def __f3():
        pass

# print(A.num)


A.f2()
# print('外部:', A.__x)
# print(A.__dict__)
print('外部:', A._A__x)

a = A()
# print(a.__name)

# A.__f3()

类的继承

1.什么继承

继承就是让子类直接拥有父类所有的属性和方法。
子类 - 继承者
父类 - 被继承者,又叫超类

2.继承的语法

class 类名(父类1, 父类2, 父类3,…):
类的内容

注意:如果在定义类的时候没有添加继承关系,那么这个类默认继承Python的基类object

class Person:
    num = 61

    def __init__(self):
        self.name = '小明'
        self.age = 18
        self.gender = '男'

    def eat(self, food):
        print(f'{self.name}在吃{food}')


class Student(Person):
    pass


print(Student.num)

stu = Student()
print(stu.name, stu.age, stu.gender)

stu.eat('面条')

3.在子类中添加属性和方法

1)添加类属性和方法
在子类中直接定义新的类属性和新的方法

2)添加对象属性
类中的方法的调用过程:先看当前类中是否有对应的方法,如果有就直接调用自己类中的这个方法;如果没有就去看父类中有没有,如果有直接调用,没有看父类的父类…以此类推,如到找object都没有找到相应的方法,才会报错。

继承的时候,子类之所以可以继承父类的对象属性,是因为继承了父类的_init__方法。如果子类中有__init_,那么父类的__init__就不会被继承,
那么对象属性就不会被继承。

总结:在子类添加__init__的同时用super()去调用父类的__init__方法

class Teacher(Person):
    profession = '老师'

    def __init__(self):
        # super().__init__()     # 调用当前类的父类的__init__()
        super(Teacher, self).__init__()
        self.school = '千锋教育'

    def teach(self):
        print('教学')

    @staticmethod
    def message():
        print('教书育人')


print(Teacher.num, Teacher.profession)

t1 = Teacher()
# t1.eat('火锅')
t1.teach()

Teacher.message()

print(t1.school)
print(t1.name, t1.age, t1.gender)

4.super的使用

super(类, 对象).方法 - 调用指定类的父类的方法 (注意:后面的对象必须是前面的类或子类的对象)
super().方法 - 调用当前类的父类的方法

class A:
    def funcA(self):
        print('A')

    def func1(self):
        print('A1')


class B(A):
    def funcB(self):
        print('B')

    def func1(self):
        print('B1')


class C(B):
    def funcC(self):
        print('C')

    def func1(self):
        print('C1')
        # super().func1()
        # super(C, self).func1()
        # super(B, self).func1()
        super(Student, Student()).eat('苹果')


print('==============================================')
c = C()
c.func1()


class Animal:
    def __init__(self, age, gender='雄'):
        self.gender = gender
        self.age = age


class Dog(Animal):
    def __init__(self, name, color, gender='雄'):
        super().__init__(0, gender)
        self.name = name
        self.color = color


a = Animal(2)

d = Dog('大黄', '黄色')

# 思考题:多继承的时候是不是所有父类的所有属性和方法都能被继承?

运算符重载

1.魔法方法

类中自带的以__开头并且以__结尾的方法就是魔法方法,所有的魔法方法都不需要程序去调用,会在特定情况下自动调用。
这些魔法方法中有一部分方法是在对象使用运算符的时候会被自动调用。

每一个运算符都有一个固定的魔法方法,某种数据是否支持某种,就看这个数据对应的类中有没有实现对应的魔法方法。

10 + 20         # 10.__add__(20)
'abc' + '234'   # 'abc'.__add__('234')

10.2 > 20

# {'a': 10} + {'b': 20}   # TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

# class A:
#     def func1(self):
#         print('A')
#
#
# class B:
#     def func1(self):
#         print('B')
#
# x = B()
# x.func1()

2.重载运算符 - 在自己的类中通过现实运算的魔法方法来让自己的类的对象支持指定的运算符
自己定义的类默认支持比较是否相等

from copy import copy


class Student:
    def __init__(self, name='小明', age=18, score=60):
        self.name = name
        self.age = age
        self.score = score

    def __repr__(self):
        return f'<{str(self.__dict__)[1:-1]}>'

    # self + other, 返回值就是加法运算的结果
    def __add__(self, other):
        # self = stu1, other=stu2
        # return self.age + other.age
        return [self, other]

    def __mul__(self, other: int):
        result = []
        for _ in range(other):
            result.append(copy(self))
        return result

    # self > other
    def __gt__(self, other):
        return self.score > other.score


stu1 = Student()
stu2 = Student('小花', 22, 45)
print(stu1 != stu2)

print(stu1 + stu2)    # stu1.__add__(stu2)
s = stu1 * 3
print(s)
stu1.name = '张三'
print(s)

students = [
    Student('stu1', 23, 98),
    Student('stu2', 18, 87),
    Student('stu3', 25, 99),
    Student('stu4', 22, 80)
]
print(students)


print(max(students))
students.sort()
print(students)

拷贝

1.浅拷贝和深拷贝

不管是浅拷贝还是深拷贝都是将被拷贝的数据复制产生一个新的数据,然后将新的数据的地址返回。
如果被拷贝的对象中有子对象(可变数据),浅拷贝不会对子对象进行拷贝(人变成不一样的人,但是狗还是同一条狗),
深拷贝会对子对象进行拷贝(人变成不一样的人,狗也会变成不一样的狗)

from copy import copy, deepcopy

class Dog:
    def __init__(self, name, color):
        self.name = name
        self.color = color

    def __repr__(self):
        return f'<{str(self.__dict__)[1:-1]}, id:{id(self)}>'


class Person:
    def __init__(self, name, age, dog=None):
        self.name = name
        self.age = age
        self.dog = dog

    def __repr__(self):
        return f'<{str(self.__dict__)[1:-1]}, id:{id(self)}>'


p1 = Person('小明', 18, Dog('大黄', '黄色'))
print('p1:', p1)

# 直接赋值  - 两个变量保存同一个数据的地址
p2 = p1
print('p2:', p2)

# 浅拷贝
p3 = copy(p1)
print('p3:', p3)

# 深拷贝
p4 = deepcopy(p1)
print('p4:', p4)

print('======================修改年龄后==================')
p1.age = 20
p1.dog.name = '旺财'
print('p1:', p1)
print('p2:', p2)
print('p3:', p3)
print('p4:', p4)

内存管理

1.内存的申请

当使用变量保存数据的时候系统会自动在堆中申请空间保存数据,同时让变量保存数据在内存中地址(python中的变量全是指针变量)。

如果需要保存的数据是不可变的数据,系统会先检查当前内存中是否已经存在这个数据,如果有直接返回已经保存的数据的地址,如果没有才会重新申请新的内存保存数据。

a = 100
b = 100
print(id(a), id(b))    # 4428060448 4428060448

x = 'abc'
y = 'abc'
print(id(x), id(y))     # 4445987760 4445987760

m = (10, 20)
n = (10, 20)
print(id(m), id(n))     # 4468933696 4468933696

l1 = [10, 20]
l2 = [10, 20]
print(id(l1), id(l2))     # 4511662208 4511664384

2.内存释放
原则:如果数据有引用数据就不会被销毁(不会释放),如果数据没有引用(引用计数为0)就会被自动销毁(释放)。

list1 = [10, 20, 30]
list2 = list1
list3 = [1, list1]

作业

1.建立一个汽车类Auto,包括轮胎个数,汽车颜色,车身重量,速度等属性,并通过不同的构造方法创建实例。至少要求 汽车能够加速 减速 停车。 再定义一个小汽车类CarAuto 继承Auto 并添加空调、CD属性,并且重新实现方法覆盖加速、减速的方法

class Auto:

    def __init__(self, tyre_count=4, color="white", weight=1400, speed=180):
        self.tyre_count = tyre_count
        self.color = color
        self.weight = weight
        self.speed = speed

    def speed_on(self, up=20):
        self.speed += up

    def speed_down(self, down=20):
        self.speed -= down

    def stop(self):
        self.speed = 0


class CarAuto(Auto):

    def __init__(self, cd="一路向北", air_conditioner="on"):
        super(CarAuto, self).__init__()
        self.cd = cd
        self.air_conditioner = air_conditioner
        
    def speed_on(self, up=40):
        self.speed += up
    
    def speed_down(self, down=40):
        self.speed -= down

2.创建一个Person类,添加一个类字段用来统计Perosn类的对象的个数

class Person:
    count = 0

    def __init__(self):
        Person.count += 1

    @staticmethod
    def ob_count():
        print(Person.count)

3.创建一个动物类,拥有属性:性别、年龄、颜色、类型 ,

要求打印这个类的对象的时候以’/XXX的对象: 性别-? 年龄-? 颜色-? 类型-?/’ 的形式来打印

class Animal:
    
    def __init__(self, gender = "雄", age=0, color="white", breed="dog"):
        self.gender = gender
        self.age = age
        self.color = color
        self.breed = breed
        
    def __repr__(self):
        return f"{self.__class__}的对象:性别-{self.gender} 年龄-{self.age} 颜色-{self.color} 类型-{self.breed}"

4.写一个扑克类, 要求拥有发牌和洗牌的功能(具体的属性和其他功能自己根据实际情况发挥)

class Poker:
    init = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"]
    poker = ["$+","$-"]
    for x in init:
        poker.append(x+"+")
        poker.append(x+"-")
        poker.append(x+"*")
        poker.append(x+"/")

    @classmethod
    def shuffle(cls):
        random.shuffle(cls.poker)

    @classmethod
    def deal(cls):
        return random.sample(cls.poker, 12)

5.(尝试)写一个类,其功能是:1.解析指定的歌词文件的内容 2.按时间显示歌词 提示:歌词文件的内容一般是按下面的格式进行存储的。歌词前面对应的是时间,在对应的时间点可以显示对应的歌词

[00:00.20]蓝莲花   
[00:00.80]没有什么能够阻挡   
[00:06.53]你对自由地向往   
[00:11.59]天马行空的生涯  
[00:16.53]你的心了无牵挂   
[02:11.27][01:50.22][00:21.95]穿过幽暗地岁月   
[02:16.51][01:55.46][00:26.83]也曾感到彷徨   
[02:21.81][02:00.60][00:32.30]当你低头地瞬间  
[02:26.79][02:05.72][00:37.16]才发觉脚下的路   
[02:32.17][00:42.69]心中那自由地世界  
[02:37.20][00:47.58]如此的清澈高远   
[02:42.32][00:52.72]盛开着永不凋零   
[02:47.83][00:57.47]蓝莲花  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值