类讲解

面向对象

一.什么是面向对象

面向对象编程是一种设计思想,其实是就是把对象作为程序的基本单元,一个对象包含需要的参数和方法等

二.术语

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
封装:对外部世界隐藏对象的工作细节
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待,以普通的类 为基础建立专门的类对象。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

三.创建类
class Name(object):
	pass
name=Name()

解释:
1.python中定义类使用class关键字,class后面紧接类名,类名通常是大写开头的单词
2.类包含属性和方法
3.一个对象的特征称为"属性",一个对象的行为称为"方法"。属性在代码层面上来看就是变量,方法实际就是函数,通过调用这些函数来完成某些工作
4.在类中定义方法的形式和函数差不多,但其不称为函数,而是叫方法。方法的调用需要绑定到特定的对象上(通过self.),而函数不需要。

四.类的使用
class MyClass():
    """一个简单的类实例"""
    i = 12345
 
    def f(self):
        return 'hello world'
 
 
x = MyClass()  # 实例化类
 
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
 
#上面代码的输出结果为:
#MyClass 类的属性 i 为: 12345
#MyClass 类的方法 f 输出为: hello world

解释:
1.在未实例化类时(x = MyClass()前),只是定义了对象的属性和方法,此时其还不是一个完整 的对象,将定义的这些称为类。需要使用类来创建一个真正的对象,这个对象就叫做这个类的一个实例,也叫作实例对象(一个类可以有无数个实例)
2.创建一个对象也叫做类的实例化,即x = MyClass()。(此时得到的x变量称为类的具体对象)注意此时类名后面是跟着小括号的,这跟调用函数一样。
3.假设x是咱们的实例,x.i用于调用类的属性,也就是我们前面所说的类变量;x.f()用于调用类的方法。
4.类中定义方法的要求:在类中定义方法时,第一个参数必须是self,除第一个参数外,类的方法和普通的函数没什么区别,如可以使用默认参数,可变参数,关键字参数和命名关键字参数等
5.在类中调用方法的要求:要调用一个方法,在实例变量上直接调用即可,除了self不用传递,其他参数正常传入

扩展:
1.类是一个抽象的概念,对象则是一个实际存在的东西。就像我们说的"狮子",它只是一个抽象的东西,只有具体到狮子这种动物身上它才是实际存在的。在比如设计房子的图纸只能告诉你房子是什么样的,并不是真正的房子,只有通过钢筋水泥建造出来的房子才实际存在,才能住人

2.self是什么:为什么方法中第一个参数必须为self

1、self其实就相当于是实例
2、如果把类比作图纸,那么由类实例化后的对象才是真正可以住人的房子。根据一张图纸就可以设计出成千上万的房子,他们都长得差不多,但他们都有不同的主人,每个人都只能回自己的家里…所以self这里就相当于每个房子的门牌号,有了self就可以轻松找到自己房子。
python的self参数就是同一个道理,有同一个类可以生成无数对象,当一个对象的方法被调用的时候,对象会将自身的引用作为第一个参数传给该方法,那么python就知道需要操作哪个对象的方法了
代码解释:

class Ball:
    def setname(self,name):
        self.name = name
    def kick(self):
        print("我叫%s" % self.name)
 
a = Ball()
b = Ball()
c = Ball()
 
a.setname("A")
b.setname("B")
c.setname("C")
 
print(a.kick())
print(b.kick())
print(c.kick())
 
#上面代码的输出结果为:我叫A、我叫B、我叫C
五.类变量和实例变量

1.实例变量是每个实例都独有的数据,而类变量是该类所有实例共享的属性和方法。其实我更愿意用类属性和实例属性来称呼它们,但是变量这个词已经成为程序语言的习惯称谓。

定义实例属性,需要使用 __init__方法。⚠️:左右都是两根下划线。def和__init__中间有空格。

2.即某个属性对于每个实例都是独有的,就需要将其定义为实例变量;是每个实例同共有的就可以定义为类属性

class Dog:
    dress = "china"
    def __init__(self,name):
        self.name = name 
dog=Dog('小黑')
print(Dog.dress)
print(dog.dress)
print(dog.name)
输出结果:
	china
	china
	小黑

解释:
1、在类中调用实例属性时使用self. ,在类外调用时使用实例名.实例实例属性名
2、类中存在__init__方法时,在实例化类时需要传入参数(实例变量的实参),在调用类的方法时也需要传入方法的实参(方法中存在形参时)

六.实例方法

1.实例方法就是类在实例化之后,才可以调用的方法,也就是只可以用过实例名来调用实例方法;
2.实质是把实例自己传递给函数,通过调用实例本身,使用实例中的参数;
3.所以一般在定义实例方法的时候,参数里都需要有self,这个self传递的是实例本身;

class Name(object):
    def __init__(self):
        self.age=12
    def run(self):
        print('我是一个实例方法')
name=Name()
name.run()
输出结果:
	我是一个实例方法
七.魔法方法

在python类中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法
魔法方法的标志:被两条下划线包围起来了,典型:__init__方法

__init__方法

__init__方法是一个 初始化方法,使用类创建实例的时候会自动调用__init__方法,给实例赋予初始化的属性

为什么定义类的时候有的时候写init方法有的时候不写init方法:
一般都会有,但是如果不需要传入类的属性参数,那么就不需要有
另外注意 在__init__方法的里面不可以写return返回任何东西

srt__方法
调用print()打印实例化对象时会调用__str__方法如果__str
()中有返回值,就会打印他的返回值。

class Cat:
    """定义一个猫类"""
 
    def __init__(self, new_name, new_age):
        """在创建完对象之后 会自动调用, 它完成对象的初始化的功能"""
        # self.name = "汤姆"
        # self.age = 20
        self.name = new_name
        self.age = new_age  # 它是一个对象中的属性,在对象中存储,即只要这个对象还存在,那么这个变量就可以使用
        # num = 100  # 它是一个局部变量,当这个函数执行完之后,这个变量的空间就没有了,因此其他方法不能使用这个变量
 
    def __str__(self):
        """返回一个对象的描述信息"""
        # print(num)
        return "名字是:%s , 年龄是:%d" % (self.name, self.age)
 
    def eat(self):
        print("%s在吃鱼...." % self.name)
 
    def drink(self):
        print("%s在喝可乐..." % self.name)
 
    def introduce(self):
        # print("名字是:%s, 年龄是:%d" % (汤姆的名字, 汤姆的年龄))
        # print("名字是:%s, 年龄是:%d" % (tom.name, tom.age))
        print("名字是:%s, 年龄是:%d" % (self.name, self.age))
 
# 创建了一个对象
tom = Cat("汤姆", 30)
print(tom)
七.单继承

一个类继承另一个类时,会自动获得另一个类的所有属性和方法,被继承的类称之为父类,新类称为子类。子类拥有父类所有的属性和方法,并且可以定义自己的属性和方法。
首先我们定义一个表示动物的父类,输出它所有的属性和方法:

class Food:
    def __init__(self):
        self.favorite_food = 'banana'
    def run(self):
    	print('我是run方法')
food=Food()
print(food.favorite_food)
food.run()
输出结果:
	banana
	我是run方法

我们再创建一个Person类,继承Food类

class Person(Food):
    def show_favorite(self):
        print("My favorite food is :" + self.favorite_food)
        
person = Person();
person.show_favorite()
person.run()

输出结果:
	My favorite food is :banana
	我是run方法

通过上方的代码咱们可以看到,子类Person中实际上是没有favorite_food的属性的,但是程序正常输出了banana
这就是子类Person继承了父类Food的__init__方法。
同样的道理,子类Person也继承了父类Food的run方法。

八.多继承

多继承,顾名思义就是一个类继承了多个父类
通过单继承咱们了解到,继承就是子类会获得父类的方法和属性
如果子类继承了多个父类,继承的顺序是就近原则
Python 中针对 类 提供了一个内置属性 mro 可以查看方法搜索顺序
MRO 是 method resolution order,主要用于在多继承时判断 方法、属性的调用路径

#多继承:子类有多个父类
class Human:
    def __init__(self, sex):
        self.sex = sex
    def p(self):
        print("这是Human的方法")
  
class Person:
    def __init__(self, name):
        self.name = name
    def p(self):
        print("这是Person的方法")
    def person(self):
        print("这是我person特有的方法")
 
class Teacher(Person):
    def __init__(self, name, age):
        super().__init__(name)
        self.age = age
 
class Student(Human, Person):
    def __init__(self, name, sex, grade):
    #要想调用特定父类的构造器可以使用父类名.__init__方式。
       Human.__init__(self,sex)
       Person.__init__(self,name)
       self.grade = grade
 
class Son(Human, Teacher):
    def __init__(self, sex, name, age, fan):
        Human.__init__(self, sex)
        Teacher.__init__(self, name, age)
        self.fan = fan
 
# ------创建对象 -------------
stu = Student("tom", "male", 88)
print(stu.name,stu.sex,stu.grade)
stu.p()  # 虽然父类Human和Person都有同名P()方法 ,但是调用的是括号里的第一个父类Human的方法
 
son1 = Son("jerry", "female", 18, "打球")
son1.person()  # 可以调用父类的父类的方法。
son1.p()  # 子类调用众多父类中同名的方法,按继承的顺序查找。
print(Teacher.__mro__)  #__mro__方法查看继承顺序

输出结果:
	tom male 88
	这是Human的方法
	这是我person特有的方法
	这是Human的方法
	(<class '__main__.Teacher'>, <class '__main__.Person'>, <class 'object'>)

九.调用父类方法

1.用类名去直接调用,这时候self参数不能省略。

class Animal:
    def __init__(self,name,age,weight):
        self.name=name
        self.age=age
        self.weight=weight
class Dog(Animal):
    def __init__(self,name,age,weight,owner):
        Animal.__init__(self,name,age,weight)#注意这里不能使用Animal(name,age,weight)
        self.owner=owner

d1=Dog('小白','2','20','小黑')
print('%s的主人是%s'%(d1.name,d1.owner))  

输出结果:
	小白的主人是小黑

可以实现基本的功能,但是可拓展性比较差,当父类名字发生修该时下面就必须进行修改。这时候可以使用super()方法就可以解决这问题。
2.使用super()方法

class Animal:
    def __init__(self,name,age,weight):
        self.name=name
        self.age=age
        self.weight=weight
class Dog(Animal):
    def __init__(self,name,age,weight,owner):
        super().__init__(name,age,weight)
        self.owner=owner

d1=Dog('小白','2','20','小黑')
print('%s的主人是%s'%(d1.name,d1.owner))

输出结果:
	小白的主人是小黑

super是安装mro列表进行查找,按照列表顺序进行继承的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值