Python(关于属性和类详细代码解释)

动态绑定属性

class Student:
    # 类属性:定义在类中,方法外的变量
    school = '北京xxx教育'
    print(type(school))  # 定义在类里面所以属性不变

    # 类属性初始化方法
    def __init__(self, xm, age):  # xm,age是方法的参数,是局部变量,xm,age的作用域整个__init__方法
        # 即xm,age只能在类里面使用,要想在其他地方使用需要定义类的实例属性
        self.name = xm  # 左例是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
        self.age = age  # 实例的名称和局部的可以相同

    # 定义在类中的函数,称为方法,自带一个参数self
    def show(self):
        print(f'我叫:{self.name}.今年:{self.age}岁了')
#创建两个Student类型的对象
stu=Student('xx',10)
stu2=Student('hh',20)
print(stu.name,stu.age)
print(stu2.name,stu2.age)

#为stu2动态绑定一个实例属性
stu2.gender='女'
print(stu2.name,stu2.age,stu2.gender)

#动态绑定的方法
def introduce():
    print('普通函数被动绑定成stu2对象的方法')
stu2.fun=introduce
#经过此操作fun就是stu2对象的方法
#对象的方法属于实例方法调用
stu2.fun()

1、单下划线开头的属性或方法表示protected受保护的成员,这类成员被视为仅供内部使用,允许类本身和子类进行访问,但实际它可以被外部代码访问。

2、双下划线开头表示private私有的成员,这类成员只允许定义该属性或方法的类本身进行访问

3、收尾双下划线表示特殊的方法

class Student():
    def __init__(self,name,age,gender):
        self._name=name #单下划线
        self.__age=age
        self.gender=gender
    def _fun1(self):
        print('受保护的')
    def __fun2(self):#私有的
        print('只有定义的类可以访问')
    def show(self):#普通类
        self._fun1()
        self.__fun2()

stu=Student('xx',10,'女')
#类的外部
print(stu._name)
# print(stu.__age)#AttributeError: 'Student' object has no attribute '__age'. Did you mean: '_name'?

#访问受保护的实例方法
stu._fun1()#子类及本身
#私有方法
# stu.__fun2()#AttributeError: 'Student' object has no attribute '__fun2'. Did you mean: '_fun1'?

#私有的实例属性
print(stu._Student__age)
stu._Student__fun2()

# print(dir(stu))#内置函数
#['_Student__age', '_Student__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', 'show']

class Student:
    def __init__(self,name,gender):
        self.name=name
        self.__gender=gender#self.__gender 是私有的实例属性
      #以上是使用下划线强制访问
    #使用装饰器(以@开头的)将方法转成属性使用
    @property
    def gender(self):
        return self.__gender

#将gender修改为可变属性
    @gender.setter#不能@property
    def gender(self,value):
        if value!='男'and value!='女':
            print('性别有误,默认为女')
        else:
         self.__gender=value


stu=Student('xy','女')
print(stu.name,'性别',stu.gender)#属性变成了方法,stu。gender()
#变成方法之后就无法修改属性值
# stu.gender='男'#AttributeError: property 'gender' of 'Student' object has no setter
#要想修改属性为可变属性,应该在前面修改代码12行
stu.gender='男'
print(stu.name,'性别',stu.gender)

Python中面向对象的三大特征:

一个子类可以继承N个父类;一个父类也可以拥有N多个子类;如果一个类没有继承任何类,那么默认继承object类。

class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def show(self):
        print(f'大家好,我是:{self.name},我今年:{self.age}岁')

#Student 继承Person类
class Student(Person):
    #编写初始化的方法
    def __init__(self,name,age,stuno):
        super().__init__(name,age)#调用父类的初始化方法
        self.stuno=stuno

#Doctor继承Person类
class Doctor (Person):
    def __init__(self,name,age,department):
         super().__init__(name,age)
         self.department=department

        #编写初始化方法
#创建第一个子类对象
stu=Student('xx',20,'1001')
stu.show()
#创建第二个子类对象
doctor=Doctor('yy',10,'外科')
doctor.show()
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('xx',20,'女')#调用Son类中的__init__执行
son.showA()
son.showB()
class Person:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def show(self):
        print(f'大家好,我是:{self.name},我今年:{self.age}岁')

#Student 继承Person类
class Student(Person):
    #编写初始化的方法
    def __init__(self,name,age,stuno):
        super().__init__(name,age)#调用父类的初始化方法
        self.stuno=stuno

    def show(self):
        #调用父类中的方法
        super().show()
        print(f'学号为:{self.stuno}')


#Doctor继承Person类
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('xx',20,'1001')
stu.show()#先调用子类的show方法,子类没有去父类中调用
doctor=Doctor('yy',10,'外科')
doctor.show()#我叫yy,我今年10岁,我的工作科室是:外科

class Person():
    def eat(self):
        print('人,吃五谷杂粮')

class Cat():
    def eat(self):
        print('猫,喜欢吃鱼')

class Dog():
    def eat(self):
        print('狗喜欢啃骨头')

#这三个类都有一个同名的方法,eat
#编写函数
def fun(obj):#obj是函数的形式参数,定义处不用知道这个形参的数据类型
    obj.eat()#通过变量obj(对象)调用eat方法

#创建三个类的对象
per=Person()
cat=Cat()
dog=Dog()

#调用fun函数
fun(per)
fun(cat)
fun(dog)

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

    def show(self):
        print(f'我叫{self.name},我今年{self.age}')

#创建Person 类的对象
per=Person('xx',20)
print(dir(per))#查看person类型
#['__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', 'show']
#以上除了'age', 'name', 'show',其他均是由object父类中调用而来

#重写父类的str方法
class Person(object):
    def __init__(self,name,age):
        self.name=name
        self.age=age

        #方法重写
    def __str__(self):
        return'这是一个具有name和age两个实例属性'#返回值是一个字符串
#创建person类的对象
per=Person('xx',19)
print(per)#__str__方法中的内容  直接输出对象名,实际上是调用__str__方法而不是内存地址
print(per.__str__())
#以上结果均为:
#这是一个具有name和age两个实例属性
#这是一个具有name和age两个实例属性

a=10
b=20
print(dir(a))#使用内置函数查看Python中一切对象
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__(2))

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=C('xx',20)

print('对象a的属性字典:',a.__dict__)#对象a的属性字典: {}
print('对象b的属性字典:',b.__dict__)#对象b的属性字典: {}
print('对象b的属性字典:',c.__dict__)#对象b的属性字典: {'name': 'xx', 'age': 20}

print('对象a所属的类:',a.__class__)#对象a所属的类: <class '__main__.A'>
print('对象b所属的类',b.__class__)#对象b所属的类 <class '__main__.B'>
print('对象c所属的的类:',c.__class__)#对象c所属的的类: <class '__main__.C'>

print('A类的父类元组',A.__bases__)
print('B类的父亲元组',B.__bases__)
print('c类的父类元组',C.__bases__)
#A类的父类元组 (<class 'object'>,)
#B类的父亲元组 (<class 'object'>,)
#c类的父类元组 (<class '__main__.A'>, <class '__main__.B'>)

print('A类的父类:',A.__base__)
print('B类的父类:',B.__base__)
print('c类的父亲',C.__base__)#A类,如果继承了N多个父类,结果只是显示第一个父类
# c类的父亲 <class '__main__.A'>

print('A类的层次结构',A.__mro__)
print('B类的子类列表:',B.__mro__)
print('C类的子类列表:',C.__mro__)#C类继承了A类,B类,间接继承了object类

print('A类的子类列表:',A.__subclasses__())#A的子类有C类,A类的子类列表: [<class '__main__.C'>]
print('B类的子类列表:',B.__subclasses__())#B类的子类列表: [<class '__main__.C'>]
print('C类的子类列表:',C.__subclasses__())#C类的子类列表: []

class CPU():
    pass
class Disk():
    pass

class Computer():
    def __init__(self,cpu,disk):
        self.cpu=cpu
        self.disk=disk

cpu=CPU()#创建了一个CPU对象
disk=Disk()#创建了一个硬盘对象

#创建一个计算机对象
com=Computer(cpu,disk)
#变量(对象)的赋值
com1=com
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com1,'子对象的内存地址',com1.cpu,com1.disk)
#赋值不会创建新的空间
# ject at 0x0000024FA3AA4B30> 子对象的内存地址: <__main__.CPU object at 0x0000024FA3AA4B90> <__main__.Disk object at 0x0000024FA3AA4B00>
# <__main__.Computer object at 0x0000024FA3AA4B30> 子对象的内存地址 <__main__.CPU object at 0x0000024FA3AA4B90> <__main__.Disk object at 0x0000024FA3AA4B00>

#类对象的浅拷贝
import copy
com2=copy.copy(com)
print(com,'子对象内存地址为',com.cpu,com.disk)
print(com2,'子对象内存地址为',com2.cpu,com2.disk)
#<__main__.Computer object at 0x000001F45ACB4EC0> 内存地址为 <__main__.CPU object at 0x000001F45ACB4F20> <__main__.Disk object at 0x000001F45ACB4E90>
#<__main__.Computer object at 0x000001F45ACB4FE0> 内存地址为 <__main__.CPU object at 0x000001F45ACB4F20> <__main__.Disk object at 0x000001F45ACB4E90>
#产生了一个新的对象,但是子对象不变

#类对象的深拷贝
print('-'*40)
com3=copy.deepcopy(com)#com3新产生的对象,com3的对象,CPU,disk也会重新创建
print(com,'子对象内存地址',com.cpu,com.disk)
print(com3,'子对象内存地址',com3.cpu,com3.disk)
#<__main__.Computer object at 0x0000020B755F5280> 子对象内存地址: <__main__.CPU object at 0x0000020B755F52E0> <__main__.Disk object at 0x0000020B755F5250>
#<__main__.Computer object at 0x0000020B755F53A0> 子对象内存地址 <__main__.CPU object at 0x0000020B755F52E0> <__main__.Disk object at 0x0000020B755F5250>
#创建新对象子对象也会改变

访问私有属性的语法:对象名._类名__属性名

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值