11-类以及实例对象

两大编程思想

两大编程思想:面向过程面向对象
西红柿炒鸡蛋举个例子:
面向过程:事物比较简单,可以用线性思维去解决。【1、打鸡蛋;2、切西红柿;3、点火;4、倒油;5、下鸡蛋;6、下西红柿;7、翻炒3分钟;8、出锅。】
面向对象:事物比较复杂,使用简单的线性无法解决。【找一个餐馆,点一份西红柿炒鸡蛋】
共同点:解决实际问题的一种思维方式。
二者相辅相成,并不是对立的。

解决复杂问题,通过面向对象方式便于我们从宏观上把握事物之间的关系,方便我们分析整个系统具体到微观操作,仍然使用面向过程的方式来处理

类与对象

类:类别,分门别类,多个类似事物组成的群体的统称,能够帮我们快速理解和判断事物的性质。
对象:100、99、500都是int类下包含的相似的不同个例、实例或者对象。

python中一切皆对象

类的创建

类的创建格式

class 类名:
pass
注意:类名建议以下列格式为准,每个单词的首字母大写,其他小写,比如:StudentInfo

类的组成

类的组成有:类属性、实例方法、静态方法、类方法、初始化方法、实例属性。
类属性—直接写在类中的变量。
实例方法—def est(self): pass
静态方法— @staticmethod def method(): pass
类方法—@classmethod def cml(cls): pass
初始化方法-- def init(self): pass
实例属性—就是定义在__init__方法中的变量;

class Student(object):
    # 类属性
    studentType = '学生'

    #初始化方法
    def __init__(self, name, age):
        #name age是实例属性
        self.name = name
        self.age = age
    
    @staticmethod
    def staticMethodInfo():
        print('我是静态方法')
    
    @classmethod
    def classMethodInfo(cls):
        print('我是类方法')
    
    def est(self):
        print("我是实例方法")

对象的创建

对象的创建,即类的实例化
格式:实例名 = 类名()

调用类中的属性【类属性、实例属性】以及方法【静态方法、实例方法、类方法】
格式:实例名.属性/方法

类属性:类中方法外的变量,被该类的所有对象所共享。
类方法:使用classmethod修饰的方法,使用类名直接调用。
静态方法:使用staticmethod修饰的方法,使用类名直接调用。

例子如下:

class Student(object):
    # 类属性
    studentType = '学生'

    #初始化方法
    def __init__(self, name, age):
        print('我是初始化方法')
        #name age是实例属性
        self.name = name
        self.age = age
    
    @staticmethod
    def staticMethodInfo():
        print('我是静态方法')
    
    @classmethod
    def classMethodInfo(cls):
        print('我是类方法')
    
    def eat(self):
        print("我是实例方法")

# 创建实例时会调用初始化方法
stu = Student('张三',23) # 我是初始化方法

#调用静态方法
Student.staticMethodInfo() # 我是静态方法
stu.staticMethodInfo() # 我是静态方法

#调用类方法
Student.classMethodInfo() # 我是类方法
stu.classMethodInfo() # 我是类方法

#调用实例方法
# Student.eat() #报错,TypeError: eat() missing 1 required positional argument: 'self'
stu.eat() # 我是实例方法

#访问类属性
print(Student.studentType) # 学生
print(stu.studentType) # 学生

#访问实例属性
# print(Student.name) #报错,AttributeError: type object 'Student' has no attribute 'name'
print(stu.name) # 张三

动态绑定属性和方法

Python是动态语言,在创建对象之后,可以动态地绑定属性和方法。

class Student(object):

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

stu = Student('张三',20)
stu.gender = '女'
print(stu.gender) # 女

def show():
    print('show方法')
stu.show = show

stu.show() # show方法

封装

封装:提高程序安全性。
将数据和行为包装到到类对象中,在方法内部对属性进行操作,在类的外部调用方法,这样,无需关心方法内部的具体实现细节,从而隔离了复杂性。
属性私有:__name = ‘xxxx’

继承

继承:提高代码的复用性。
格式:
class 子类名(父类1,父类2):
pass
如果一个类没有继承任何类,则默认继承object类。
python支持多继承。
定义子类时,必须在其构造函数中调用父类的构造方法:super().init()

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

class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade

per = Person('大明',56)
print(per.age) # 56
print(per.name) # 大明
stu = Student('小明',23,100)
print(stu.name) # 小明
print(stu.age) # 23
print(stu.grade) # 100

方法重写

如果子类对继承自父类的某个属性或方法不满意,可以在子类中对其进行重新编写。子类重写后的方法中可以通过super().xx()调用父类中被重写的方法。

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def printInfo(self):
        print('我叫'+str(self.name)+',今年'+str(self.age)+'岁了')
        

class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade
    
    #方法重写
    def printInfo(self):
        super().printInfo()
        print('我还是个学生,'+str(self.grade))

per = Person('大明',56)
stu = Student('小明',23,100)
per.printInfo()
stu.printInfo()

object类

object类是所有类的父类,因此所有类都有object类的属性和方法。
内置函数dir()可以查看指定对象所有属性。
object有一个__str__()方法用于返回一个对于’对象的描述’,对应内置函数str(),经常用于print()方帮我们查看对象的信息,所有我们经常会对__str__()进行重写。

print(dir(object))
print(object)
print(str(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 'object'>
# <class 'object'>

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def printInfo(self):
        print('我叫'+str(self.name)+',今年'+str(self.age)+'岁了')

per = Person('大明',56)
print(dir(Person))
print(Person)
# ['__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__', 'printInfo']
# <class '__main__.Person'>

print(per) # <__main__.Person object at 0x000001A3ACDC8358>
print(dir(per)) #实例对象比类中多了实例属性
# ['__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', 'printInfo']

class Person1:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def printInfo(self):
        print('我叫'+str(self.name)+',今年'+str(self.age)+'岁了')
    
    #重写str方法
    def __str__(self):
        super().__str__()
        print('打印Person类的信息')
        return 'Person1'
print(Person1('11',34))
# 打印Person类的信息
# Person1

多态

多态具有多种形态,即使不知道一个变量所引用的对象到底是什么类型,任然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。

class Person:
    def eat(self):
        print('Person eat')

class Animal:
    def eat(self):
        print("Animal eat")

class Dog(Animal):
    def eat(self):
        print("Dog eat")
class Cat(Animal):
    def eat(self):
        print("Cat eat")

def fun(classObject):
    classObject.eat()

p = Person()
fun(p) # Person eat

a = Animal()
fun(a) # Animal eat
d = Dog()
fun(d) # Dog eat
c = Cat()
fun(c) # Cat eat

注意:静态语言和动态语言关于动态的区别:
静态语言实现多态的三个必要条件:继承、方法重写、父类引用指向子类对象。
动态语言的多态崇尚"鸭子类型",在鸭子类型中不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为。

特殊方法和特殊属性

特殊属性

 -------A -----      B
|                 |       |
D               C  = C
				实例x
  1. dict—获取类对象和实例对象所绑定的所有属性和方法
  2. x.class–输出实例对象所属的类
  3. C.bases:输出C类父类(A|B)
  4. C.base----输出C类第一个父类(A)
  5. C.mro-----类的层次关系;
  6. A.subclasses()----A类的子类列表(D,C)
class A:
    pass

class B:
    pass

class D(A):
    pass

class C(A,B):
    pass

c = C()
print(A.__dict__)
#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
# <class '__main__.C'>
print(c.__class__) # <class '__main__.C'>
print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)
print(C.__base__) # <class '__main__.A'>
print(C.__mro__) # (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
print(A.__subclasses__()) # [<class '__main__.D'>, <class '__main__.C'>]

特殊方法

  • len()–通过重写__len__()方法让内置函数len()的参数可以是自定义类型。
  • add()–通过重写__add__()方法,可以使用自定义对象具有+的功能。
  • new()—用于创建对象。
  • init()----对创建的对象进行初始化。

类的浅拷贝与深拷贝

变量的赋值操作只是形成两个变量,实际上还是指向同一个对象。
浅拷贝:Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝。
深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,原对象和拷贝对象所有的子对象也不相同。

class Person:
    def __init__(self,name,age) -> None:
        self.name = name
        self.age = age
# 浅拷贝
p = Person('小明',23)
p1 = p 
print(id(p)) # 2538254986824
print(id(p1)) # 2538254986824
#实例p和实例p1的指向的内存地址是一样

#深拷贝
from copy import deepcopy
p2 = deepcopy(p)
print(id(p)) # 2536288185648
print(id(p2)) # 2536288322392
#实例p和实例p1的指向的内存地址是不一样,不是同一个内存地址。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值