11.27面向对象

创建类的语法 

定义python中的类类属性直接定义在类里面的变量

实体属性

将外部传入的变量进行赋值
实例方法类里面的函数,注意要加self
静态方法括号内无变量
类方法括号内为cls
class Student:
    #直接写到类里面的变量,称为类属性
    native_place = '湖南'
    home = '湖南' 
    def __init__(self,name,age):
        #self.name 和self.age 是实体属性,进行了一个赋值操作,将局部变量的 name 赋值给实体属性
        self.name = name
        self.age = age
    #实例方法:相当于是类里面的函数
    def eat(self):
        print(self.name + '在吃饭')
    #静态方法
    @staticmethod
    def method1():
        print('这里使用了staticmethod进行修饰,所以这是静态方法')
    #类方法
    @classmethod
    def mathod2(cls):
        print('这里使用了classmethod进行修饰,所以这是类方法')

 创建实例对象

相当于C语言中的结构体

1.创造实例对象

#创造Student类的实例对象
stu1 = Student('张三',20)
stu2 = Student('李四',15)
'''
print(stu1)#<__main__.Student object at 0x000001BD8FD0AE00>
print(type(stu1))#<class '__main__.Student'>
print(id(stu1))#1913673264640 ->输出的是该对象的内存地址
'''

2.实例方法调用

#实例方法的调用
stu1.eat()#张三在吃饭 对象名.方法名()
Student.eat(stu1)#张三在吃饭   类名.方法名(类的对象)

3.实体属性调用

#实体属性的调用
print(stu1.name)#张三
print(stu1.age)#20

 4.类属性使用方法

#类属性的使用方式
print(Student.native_place)#湖南
print(stu1.native_place)#湖南
print(stu2.home)#湖南
Student.native_place = '广东'
print(Student.native_place)#广东
print(stu1.native_place)#广东
print(stu2.native_place)#广东

 4.类方法和静态方法的使用

#类方法的使用方式
Student.mathod2()#这里使用了classmethod进行修饰,所以这是类方法

#静态方法的使用方式
Student.method1()#这里使用了staticmethod进行修饰,所以这是静态方法

动态绑定属性和方法

1.动态绑定属性

#为stu1动态绑定属性
stu1.gender = '女'
print(stu1.name,stu1.age,stu1.gender)#张三 20 女

2.动态绑定方法

#为stu2动态绑定方法
stu1.eat()
stu2.eat()

#先新定义一个函数
def show():
    print('这里我们新定义了一个函数,并将函数绑定给stu2')
stu2.show = show
stu2.show()

面向对象三大特征:封装 继承 多态

封装提高程序的安全性
继承提高代码复用性
多态提高程序的可扩展性和可维护性    

封装:

如果不希望在类外使用某一实体属性,可以在实体属性前加__

class Student:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def printage(self):
        print(self.__age)
stu1 = Student('张三',18)
print(stu1.name)
#print(stu1.__age)AttributeError: 'Student' object has no attribute '__age'

继承:

1.继承的实现方法

利用super()函数,调用父类的实例属性

class Person(object):
    #定义父类的实体属性
    def __init__(self,name,age):
        self.name = name
        self.age = age
    #定义父类的实例方法
    def info(self):
        print(self.name,self.age)

#定义Person的子类
class Student(Person):
    def __init__(self,name,age,num):
        #继承父类的实体属性
        #super调用父类
        super().__init__(name,age)
        self. num = num

class Teacher(Person):
    def __init__(self,name,age,teachofyear):
        super().__init__(name,age)
        self.teachofyear = teachofyear

stu = Student('张三',20,100012)
teacher = Teacher('李四',55,35)

stu.info()#张三 20
print(teacher.teachofyear)#35

2.继承的方法重写

利用super()函数调用父类中的实例方法

lass Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def info(self):
        print(self.name,self.age)

class Teacher(Person):
    def __init__(self,name,age,teachofyear):
        super().__init__(name,age)
        self.teachofyear = teachofyear
    def info(self):
        super().info()
        print(self.teachofyear)

teacher = Teacher('李四',55,35)
teacher.info()#35

3.重写object类的属性

我们先定义一个Player类,默认父类为object类

class Player:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):
        print('{}今年{}岁了'.format(self.name,self.age))

player = Player('Messi',35)
#内置函数dir()可以查看指定对象的所有属性
print(dir(player))
#['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
#其中的__str__()方法用于返回对对象的描述,所以我们对str()进行重写
player.__str__()#Messi今年35岁了

多态:

简而言之就是,具有多种形态,指的是在调用函数时,就算不知道参数的数据类型,仍然可以灵活调用对象中的哪个方法。

#父类
class Animal(object):
    def eat(self):
        print('动物要吃东西')

#子类
class Dog(Animal):
    def eat(self):
        print('狗吃肉')

class Cat(Animal):
    def eat(self):
        print('猫吃鱼')
class People(object):
    def eat(self):
        print('人吃五谷杂粮')

def fun(Animal):
    Animal.eat()

fun(Dog())
fun(Cat())
fun(People())
'''
狗吃肉
猫吃鱼
人吃五谷杂粮
'''

具体结构图如下

 当调用fun()函数时,传入的参数为Animal类型,但是当我们传入People类型时,因为People类也有.eat的实例方法,所以也可以调用。

特殊属性和特殊方法

特殊属性__dict__获得对象的所有属性和方法的字典
__class__获得实例对象所属的类型
__subclasses__获得对象的子类的列表
__bases__获得对象所属的所有父类的元组
__mro__获得对象的层次结构
print(dir(object))
#['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
class A(object):
    pass
class B(object):
    pass
class C(A,B):
    def __init__(self,name):
        self.name = name
class D(A):
    pass

x = C('messi')#x为实例对象
print(x.__dict__)#{'name': 'messi'} 输出实例对象的属性字典
print(C.__dict__)#{'__module__': '__main__', '__init__': <function C.__init__ at 0x0000026D502FD900>, '__doc__': None} 输出类的属性和方法

print(x.__class__)#<class '__main__.C'> 输出实例对象所属的类型

print(C.__base__)#<class '__main__.A'> 输出了对象所属的第一个父类
print(C.__bases__)#(<class '__main__.A'>, <class '__main__.B'>) 输出了对象所属的父类的元组

print(C.__mro__)#(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 输出了对象的层次结构

print(A.__subclasses__())#[<class '__main__.C'>, <class '__main__.D'>] 输出了对象A的子类
特殊方法__add__()通过重写__add__()方法,让自定义对象有 + 的功能 
__len__()通过重写__len__()方法,让内置函数len()的参数可以是自定义类型(对象) 
__new__()创建对象
__init__()对创建的变量进行初始化
class Person(object):
    def __new__(cls, *args, **kwargs):
        print('__new__被调用执行了,cls的id值为{}'.format(id(cls)))
        obj = super().__new__(cls)
        print('创建的对象的id为{}'.format(id(obj)))
        return obj
    def __init__(self,name,age):
        self.name = name
        self.age = age

print('object这个类对象的id为:{}'.format(id(object)))
print('Person这个类对象的id为:{}'.format(id(Person)))

#创建Person类的实例对象
p1 = Person('Messi', 34)
print('p1这个Person类的实例对象的id为:{}'.format(id(p1)))
'''
object这个类对象的id为:140709393938304
Person这个类对象的id为:2182558880432
__new__被调用执行了,cls的id值为2182558880432
创建的对象的id为2182567411472
p1这个Person类的实例对象的id为:2182567411472
'''

类的赋值与浅拷贝深拷贝

1.类的赋值

变量的赋值操作只是形成两个变量,实际上还是指向同一个变量

class Computer(object):
    def __init__(self,disk,cpu):
        self.disk = disk
        self.cpu = cpu
class Disk(object):
    pass
class Cpu(object):
    pass

disk = Disk()
cpu = Cpu()
computer1 = Computer(disk,cpu)
computer2 = computer1
print(computer1,id(computer1))#<__main__.Computer object at 0x0000016E8172BAF0> 1574129810160
print(computer2,id(computer2))#<__main__.Computer object at 0x0000016E8172BAF0> 1574129810160
#我们可以发现,computer1和computer2的id和value一模一样
#所以变量的赋值操作只是形成两个变量,实际上还是指向同一个变量

2.浅拷贝

浅拷贝时,源对象和拷贝对象会引用同一个子对象

class Computer(object):
    def __init__(self,disk,cpu):
        self.disk = disk
        self.cpu = cpu
class Disk(object):
    pass
class Cpu(object):
    pass

import copy
computer1 = Computer(disk,cpu)
computer2 = copy.copy(computer1)
print(computer1.cpu,id(computer1))#<__main__.Cpu object at 0x000001AB850BBAC0> 1836183173584
print(computer2.cpu,id(computer2))#<__main__.Cpu object at 0x000001AB850BBAC0> 1836183173248
#我们可以发现,进行浅拷贝的同时,computer1和computer2的id不同,然而computer1和computer2中子对象相同
#所以源对象和拷贝对象会引用同一个子对象

3.深拷贝

在进行深拷贝时,拷贝对象包含子对象,源对象和拷贝对象不相同

class Computer(object):
    def __init__(self,disk,cpu):
        self.disk = disk
        self.cpu = cpu
class Disk(object):
    pass
class Cpu(object):
    pass

import copy
computer3 = copy.deepcopy(computer1)
print(computer1.cpu,id(computer1))#<__main__.Cpu object at 0x000002627190FAC0> 2621835377104
print(computer3.cpu,id(computer3))#<__main__.Cpu object at 0x000002627190C9A0> 2621835377008
#我们可以发现,进行深拷贝的同时,computer1和computer3的id和子对象都不相同
#所以在进行深拷贝时,拷贝对象包含子对象,源对象和拷贝对象不相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值