Python第九章(面向对象基础--属性,继承,dir查看,内存地址,权限等等和银行账户题目,圆的面积周长)

面向对象

创造对象

示例代码:类的名字用小驼峰命名法

python 复制代码
#编写Person类
class Person():
    pass
class Cat:  #,小括号可以省略
    pass
#对象名=类名
per=Person()
c=Cat()  #小括号不能省略
print(type(per))
print(type(c))

代码结果:

<class 'main.Person'>

<class 'main.Cat'>

类的基本组成

示例代码:

python 复制代码
class School:
#类属性,定义在类中,方法外的变量
    school="北京XXX教育"
#创建初始方法,定义实例属性
    def __init__(self,xm,age):#xm,age是参数,属于局部变量
        self.name=xm #左边是实例属性,右边是局部变量,进行赋值
        self.age=age #可以相同
    #定义类的函数,称为方法,自带参数self
    def show(self):
        print(f"我叫{self.name},今年{self.age}")#运用实例属性
    #静态方法
    @staticmethod
    def sm():
        print("这是静态方法,不能调用实例属性,也不能调用实例方法")
    @classmethod
    def cm(cls):#自带cls
        print("这是类方法,不能调用实例属性,也不能调用实例方法")
#创建类的对象
 # __int__(self,xm,age):两个参数需要传入
stu=School("111",18)
print(type(stu))
#实例属性,运用对象名打点调用
print(stu.name,stu.age)
#类属性,用类名打点调用
print(School.school)
#实例方法,使用对象名打点调用
stu.show()
#静态方法
School.sm()
#类方法
School.cm()

代码结果:

<class 'main.School'>

111 18

北京XXX教育

我叫111,今年18

这是静态方法,不能调用实例属性,也不能调用实例方法

这是类方法,不能调用实例属性,也不能调用实例方法

动态绑定属性和方法

就是在类的外面书写实例属性或者实例方法

示例代码:

python 复制代码
class School:
#类属性,定义在类中,方法外的变量
    school="北京XXX教育"
#创建初始方法,定义实例属性
    def __init__(self,xm,age):#xm,age是参数,属于局部变量
        self.name=xm #左边是实例属性,右边是局部变量,进行赋值
        self.age=age #可以相同
    #定义类的函数,称为方法,自带参数self
    def show(self):
        print(f"我叫{self.name},今年{self.age}")#运用实例属性
stu=School("001",18)
stu2=School("009",18)
print(stu.name,stu.age)
print(stu2.name,stu2.age)
#为stu2动态绑定一个实例属性
stu2.gender="男"
print(stu2.name,stu2.age,stu2.gender)
#为stu2动态绑定一个实例方法
def introduce():
    print("将这个函数动态绑定给stu2")
stu2.fun=introduce #函数的一个赋值
#fun为方法和show一样
#打点调用
stu2.fun()

代码结果:

001 18

009 18

009 18 男

将这个函数动态绑定给stu2

属性设置

将方法改为属性,属性可直接赋值

示例代码:

python 复制代码
class Student:
    def __init__(self,name,gender):
        self.name=name
        self.__gender=gender
#使用@property将方法转换为属性
    @property
    def gender(self):
        return self.__gender
#将gender这个属性设置为可写属性,解决stu.gender不能直接赋值的问题
    @gender.setter
    def gender(self,value):
        if value!="男" and value!="女":
            print("性别输入错误,默认为男")
            self.__gender="男"
        else:
            self.__gender=value

stu=Student("李佳怡","女")
print(stu.name,"的年龄是",stu.gender)
stu.gender="其他"
print(stu.name,"的年龄是",stu.gender)

代码结果:

李佳怡 的年龄是 女

性别输入错误,默认为男

李佳怡 的年龄是 男

多态

示例代码:

python 复制代码
class Person:
    def eat(self):
        print("人,吃五谷杂粮")
class Cat:
    def eat(self):
        print("猫,吃鱼")
class Dog:
    def eat(self):
        print("狗,吃骨头")
def fun(obj):
    obj.eat()
per=Person()
cat=Cat()
dog=Dog()
#python的多态不关心对象数据类型,只关心对象是否有同名方法
fun(per)
fun(cat)
fun(dog)

代码结果:

人,吃五谷杂粮

猫,吃鱼

狗,吃骨头

继承

示例代码:可以继承别人的属性或者方法,,被继承的称为父类

python 复制代码
class Person:#不写括号,默认object类
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def show(self):
        print(f"我叫{self.name},今年{self.age}岁")
class Student(Person):
    def __init__(self,name,age,sno):
        super().__init__(name,age) #调用父类的初始化方法
        self.sno=sno
class Doctor(Person):
    def __init__(self,name,age,department):
        super().__init__(name,age) #调用父类的初始化方法
        self.department=department
#创建对象
stu=Student("联名卡",18,1001)
stu.show()#可以直接调用父类的方法
doctor=Doctor("藏宝阁",54,"外科")
doctor.show()

代码结果:

我叫联名卡,今年18岁

我叫藏宝阁,今年54岁

多继承

示例代码:

python 复制代码
class Fathera:
    def __init__(self,name):
        self.name=name
    def showa(self):
        print("这是父类a的方法")
class Fatherb:
    def __init__(self,age):
        self.age=age
    def showb(self):
        print("这是父类b的方法")
class Son(Fathera,Fatherb):
    def __init__(self,name,age,gender):
        Fathera.__init__(self,name)
        Fatherb.__init__(self,age)
        self.gender=gender
son=Son("李佳怡",18,"男")
son.showa()
son.showb()

代码结果:

这是父类a的方法

这是父类b的方法

方法重写

示例代码:

python 复制代码
class Person:#不写括号,默认object类
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def show(self):
        print(f"我叫{self.name},今年{self.age}岁")
class Student(Person):
    def __init__(self,name,age,sno):
        super().__init__(name,age) #调用父类的初始化方法
        self.sno=sno
    def show(self):  #改写方法名字要和父类一样
        super().show() #调用父类的show方法
        print(f"我的学号是{self.sno}")
class Doctor(Person):
    def __init__(self,name,age,department):
        super().__init__(name,age) #调用父类的初始化方法
        self.department=department

    def show(self):  # 改写方法名字要和父类一样
        # super().show()   #调用父类的show方法
        # 可以不继承父类全部重写
        print(f"我叫{self.name},今年{self.age},我的工作科室为是{self.department}")
#创建对象
stu=Student("联名卡",18,1001)
stu.show()
doctor=Doctor("藏宝阁",54,"外科")
doctor.show()

代码结果:

我叫联名卡,今年18岁

我的学号是1001

我叫藏宝阁,今年54,我的工作科室为是外科

权限控制

示例代码:

python 复制代码
class School:
#类属性,定义在类中,方法外的变量
    school="北京XXX教育"
#创建初始方法
    def __init__(self,xm,age,gender):#xm,age是参数,属于局部变量
        self._name=xm #受保护,只能子类和本类进行访问
        self.__age=age #表示私有的,只能类本身进行访问
        self.gender = gender#普通实例属性,内部,外部,子类都可以进行访问
    def _fun1(self):
        print("受保护,只能子类和本类进行访问")
    def __fun2(self):
        print("表示私有的,只能类本身进行访问")
    def show(self):
        self._fun1() #类本身访问受保护方法
        self.__fun2()#类本身访问受私有方法
        print(self._name)#受保护实例属性
        print(self.__age)#私有的实例属性
stu=School("搓麻将",18,"man")
#类的外部
print(stu._name)
# print(stu.__age)  会报错 私有,出了类的定义范围就不能用了
#调用受保护的实例方法
stu._fun1()
#stu.__fun2()  会报错 私有,出了类的定义范围就不能用了
#私有的实例方法和属性也可以访问,但是有自己的形式
print(stu._School__age)
stu._School__fun2()
print(dir(stu))  #展示出所有的属性和方法

代码结果:

搓麻将

受保护,只能子类和本类进行访问

18

表示私有的,只能类本身进行访问

'_School__age', '_School__fun2', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_fun1', '_name', 'gender', 'school', 'show'

查看指定对象的属性,全部方法(dir)

示例代码:

python 复制代码
class School:
#类属性,定义在类中,方法外的变量
    school="北京XXX教育"
#创建初始方法,定义实例属性
    def __init__(self,xm,age):#xm,age是参数,属于局部变量
        self.name=xm #左边是实例属性,右边是局部变量,进行赋值
        self.age=age #可以相同
    #定义类的函数,称为方法,自带参数self
    def show(self):
        print(f"我叫{self.name},今年{self.age}")#运用实例属性
stu=School("李佳怡",18)
print(dir(stu))
print(stu)#自动调用__str__方法

代码结果:

'__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name', 'school', 'show'

<main.School object at 0x00000119EB827CD0>

特殊属性

示例代码:

python 复制代码
class A:
    pass
class B:
    pass
class C(A,B):
    def __init__(self,name,age):
        self.name=name
        self.age=age
a=A()
b=B()
c=C("李佳怡",18)
print("对象a的属性字典",a.__dict__)
print("对象b的属性字典",b.__dict__)
print("对象c的属性字典",c.__dict__)
print()
print("对象a所属的类",a.__class__)
print()
print("A类的父类元组",A.__bases__)
print("C类的父类元组",C.__bases__)
print()
print("A类的父类",A.__base__)
print("C类的父类",C.__base__)#显示第一个父类,如果n个父类具有同名的方法,调用第一个父类的方法
print()
print("A类的层次结构:",A.__mro__)
print("C类的层次结构:",C.__mro__)
print()
print("A类的子类列表",A.__subclasses__())#方法,要带括号
print("B类的子类列表",B.__subclasses__())
print("C类的子类列表",C.__subclasses__())

代码结果:

对象a的属性字典 {}

对象b的属性字典 {}

对象c的属性字典 {'name': '李佳怡', 'age': 18}

对象a所属的类 <class 'main.A'>

A类的父类元组 (<class 'object'>,)

C类的父类元组 (<class 'main.A'>, <class 'main.B'>)

A类的父类 <class 'object'>

C类的父类 <class 'main.A'>

A类的层次结构: (<class 'main.A'>, <class 'object'>)

C类的层次结构: (<class 'main.C'>, <class 'main.A'>, <class 'main.B'>, <class 'object'>)

A类的子类列表 [<class 'main.C'>]

B类的子类列表 [<class 'main.C'>]

C类的子类列表 []

特殊方法

示例代码:

python 复制代码
a=10
b=20
print(dir(a))
print(a.__add__(b))
print(a.__sub__(b))
print(f"{a}<{b}?",a.__lt__(b))
print(f"{a}<={b}?",a.__le__(b))
print(f"{a}={b}?",a.__eq__(b))
print("-"*40)
print(f"{a}>{b}?",a.__gt__(b))
print(f"{a}>={b}?",a.__ge__(b))
print(f"{a}!={b}?",a.__ne__(b))
print("-"*40)
print(a.__mul__(b))#乘法
print(a.__truediv__(b))#除法
print(a.__mod__(b))#取余
print(a.__floordiv__(b))#整除
print(a.__pow__(b))#幂运算

代码结果:

'__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_count', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes'

30

-10

10<20? True

10<=20? True

10=20? False


10>20? False

10>=20? False

10!=20? True


200

0.5

10

0

100000000000000000000

重写__str__方法

示例代码:

python 复制代码
class School:
#类属性,定义在类中,方法外的变量
    school="北京XXX教育"
#创建初始方法,定义实例属性
    def __init__(self,xm,age):#xm,age是参数,属于局部变量
        self.name=xm #左边是实例属性,右边是局部变量,进行赋值
        self.age=age #可以相同
    #方法重写
    def __str__(self):
        return "他具有姓名和年龄两个实例属性"

stu=School("李佳怡",18)
print(stu)#自动调用__str__方法,默认输出内存地址,修改后按修改的内容输出
#也可以手动调用
print(stu.__str__())

运行结果:

他具有姓名和年龄两个实例属性

他具有姓名和年龄两个实例属性

类的浅拷贝和深拷贝

针对于内存地址,直接赋值和浅拷贝,深拷贝各不相同

示例代码:

python 复制代码
class CPU:
    pass
class Disk:
    pass
class Computer:
    def __init__(self,cpu,disk):
        self.cpu=cpu
        self.disk=disk
cpu=CPU()
disk=Disk()
com=Computer(cpu,disk)
#变量赋值
com1=com
print(com,"子对象的内存地址:",com.cpu,com.disk)
print(com1,"子对象的内存地址:",com1.cpu,com1.disk)
print()
#类对象的浅拷贝
import copy
com2=copy.copy(com)
print(com)  #com和com2的内存地址不同,但是子对象内存地址相同
print(com2)
print(com,"子对象的内存地址:",com.cpu,com.disk)
print(com2,"子对象的内存地址:",com2.cpu,com2.disk)
print()
#深拷贝
com3=copy.deepcopy(com)#连子对象的内存空间也会重新去创建
print(com,"子对象的内存地址:",com.cpu,com.disk)
print(com3,"子对象的内存地址:",com3.cpu,com3.disk)

代码结果:(观察什么相同什么不同即可)

<main.Computer object at 0x0000020991C30190> 子对象的内存地址: <main.CPU object at 0x0000020991C30110> <main.Disk object at 0x0000020991C30150>

<main.Computer object at 0x0000020991C30190> 子对象的内存地址: <main.CPU object at 0x0000020991C30110> <main.Disk object at 0x0000020991C30150>

<main.Computer object at 0x0000020991C30190>

<main.Computer object at 0x0000020991C30210>

<main.Computer object at 0x0000020991C30190> 子对象的内存地址: <main.CPU object at 0x0000020991C30110> <main.Disk object at 0x0000020991C30150>

<main.Computer object at 0x0000020991C30210> 子对象的内存地址: <main.CPU object at 0x0000020991C30110> <main.Disk object at 0x0000020991C30150>

<main.Computer object at 0x0000020991C30190> 子对象的内存地址: <main.CPU object at 0x0000020991C30110> <main.Disk object at 0x0000020991C30150>

<main.Computer object at 0x00000209918D6F50> 子对象的内存地址: <main.CPU object at 0x0000020991C30310> <main.Disk object at 0x0000020991C30B90>

相关题目示例

计算圆的面积和周长

python 复制代码
class Circle:
    def __init__(self,r):
        self.r=r
    def get_area(self):
        return 3.14*pow(self.r,2)
    def get_perimeter(self):
        return 3.14*2*self.r
r=eval(input("请输入圆的半径"))
c=Circle(r)
area=c.get_area()
perimeter=c.get_perimeter()
print("圆的面积为:",area)
print("圆的周长为",perimeter)

代码结果:

请输入圆的半径4

圆的面积为: 50.24

圆的周长为 25.12

银行账户

python 复制代码
class Account_bank:
    def __init__(self,account_number,owner,balance):
        self.account_number=account_number
        self.owner=owner
        self.balance=balance
    def display(self):
        print(f"账号:{self.account_number}")
        print(f"户主:{self.owner}")
        print(f"账户余额:{self.balance}")

    def deposit(self):
        data=eval(input("请输入你要存多少钱:"))
        money=self.balance
        self.balance=data+money
        self.get_balance()
    def withdraw(self):
        data2=eval(input("请输入你要取多少钱:"))
        self.balance-=data2
        self.get_balance()
    def get_balance(self):
        print(f"现有余额:{self.balance}")
data_1={
    "账号":"127",
    "户主":"张三",
    "余额":4000
}
data_2={
    "账号":"124",
    "户主":"李四",
    "余额":3000
}
data_3={
    "账号":"128",
    "户主":"王五",
    "余额":6000
}
user=input("请输入你的账户:")
if user==data_1["账号"]:
    account_number=user
    owner=data_1["户主"]
    balance = data_1["余额"]
elif user==data_2["账号"]:
    account_number = user
    owner=data_2["户主"]
    balance = data_2["余额"]
else:
    account_number = data_3["账号"]
    owner=data_3["户主"]
    balance = data_3["余额"]


account=Account_bank(account_number,owner,balance)
account.display()
account.deposit()
account.withdraw()

代码结果:

请输入你的账户:127

账号:127

户主:张三

账户余额:4000

请输入你要存多少钱:100

现有余额:4100

请输入你要取多少钱:0

现有余额:4100

相关推荐
-XWB-11 分钟前
【LLM】使用MySQL MCP Server让大模型轻松操作本地数据库
人工智能·python·自然语言处理
小萌新上大分12 分钟前
SpringCloudGateWay
java·开发语言·后端·springcloud·springgateway·cloudalibaba·gateway网关
PacosonSWJTU1 小时前
python基础-13-处理excel电子表格
开发语言·python·excel
froginwe111 小时前
Perl 条件语句
开发语言
小军要奋进2 小时前
httpx模块的使用
笔记·爬虫·python·学习·httpx
啥都鼓捣的小yao2 小时前
利用C++编写操作OpenCV常用操作
开发语言·c++·opencv
灼华十一2 小时前
Golang系列 - 内存对齐
开发语言·后端·golang
程序媛学姐2 小时前
SpringRabbitMQ消息模型:交换机类型与绑定关系
java·开发语言·spring
努力努力再努力wz2 小时前
【c++深入系列】:类与对象详解(中)
java·c语言·开发语言·c++·redis
Johnny_Cheung2 小时前
字符串、列表、元组、字典
开发语言·python