大佬教程收集整理的这篇文章主要介绍了Python——什么是面向对象?类的定义、self和继承详解,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
创作不易c;来了的客官点点关注c;收藏c;订阅一键三连❤ὡc;
往期系列
Python——函数大全及使用方法! lambda?global?
Python——流程控制c;pass?break?conTinue?这些你弄清楚了吗?
目录
常见的三种编程范式
函数式编程
面向过程编程
面向对象编程 (OOP-Object Oriented ProgrAMMing)
面向过程VS面向对象
面向对象的基本概念
类(class申明)
类:用来描述具有相同属性和方法的对象的集合c;分为基类、子类。
对象
类的实例化
类的定义与使用
类空间和实例空间
类的基本特点
类的定义与使用
__init__方法
__new__方法
__init__与__new__总结
小练习:创建类c;实现计算学生的总成绩与平均分
类的self方法
类-self
练习:用面向对象实现斐波那契数列
类的继承
面向对象的好处
继承
使用继承的好处
python的多态
练习:利用类自定义异常类
• 函数可以作为参数传递、修改c;或作为返回值
• 函数内不修改外部变量的状态
• 根据操作数据的语句块来实现功能。
def login(username,passwd):
if username == "root" and passwd == "123456":
return True
else:
return false
• 把数据和功能结合起来c;用称为对象的东西包裹起来组织程序的方法。
class Logincheck():
# 登陆数据
username = "root"
passwd = "123456"
# 登录功能
def login(self,username,passwd):
if username == "root" and passwd == "123456":
return True
else:
return false
• 面向过程是一件事"该怎么做", 着重于做什么。
面向过程 = 分析问题 + 逻辑
优点:性能比面向对象高c;因为类调用时需要实例化c;开销比较大c;比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发c;性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
• 面向对象是一件事"该让谁来做"c;着重于谁去做
优点:易维护、易复用、易扩展c;由于面向对象有封装、继承、多态性的特性c;可以设计出低耦合的系统c;使系统 更加灵活、更加易于维护
缺点:性能比面向过程低
• 对象:通过类定义的数据结构实例。
• 对象包括两个数据成员(类变量和实例变量)和方法。
示例代码:
class Bus317(object):
# 类属性
line = "317"
# 方法-->行为
def run(self,flag):
print("bus317 is run")
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
实例化:创建了一个对象
bus01 = Bus317()
bus02 = Bus317()
什么是类?
生活例子:车可以理解为一个类c;特征:有车轮、车牌c;方法:会跑
基类/子类
车-->基类;摩托车c;大卡车-->子类
实例:具体的某一个事务c;某个类型实实在在的一个例子
通过类创建的一个具体的实例c;类的具体对象;
类就是一个生产实例的工厂c;类就是一个模型图
实例化
lg1 = Logincheck()
lg1就是一个对象c;实例去干活
print(lg1.login("root1","21323"))
创建类的时候就会创建类空间
实例化对象时就会生成实例空间c;不同的实例有单独的空间
实例查找属性方法时c;会现在实例空间查找c;找不到就去类空间查找c;类空间找不到就去父空间查找
eg:bus01.xx --> 查找xx属性
先在他自己的实例空间查找--找不到就去Bus317里找--再找不到再去object找--最后找不到就报错
• 封装(Encapsulation)
在类中对数据的赋值、内部调用对外部用户是透明的
把一些功能的实现细节不对外暴露
将数据和函数做了一层封装c;封装成类c;使用者不需要管具体实现的代码
• 继承(InheritancE)
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。
目的:为实现代码的重用c; 一个类可以派生出子类
继承也允许把一个派生类的对象作为一个基类对象对待。
• 多态(Polymorphism)
• 类名的规范
一般首字母大写(大驼峰)
Person, GoodsInfo
• 函数的命名
由小写字母和下划线组成
scan_book, drink
• 类的定义方式(关键字:class)
python2 => 经典类和新式类
python3 => 新式类
继承了object类的类都属于新式类c;没有继承的属于经典类
class A():
pass
class B:
pass
class C(object):
pass
python3中以上三种定义没有区别c;默认会继承object类
class Bus317(object):
# 类属性
line = "317"
# 方法-->行为
def run(self,flag):
print("bus317 is run")
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
#实例化:创建了一个对象
bus01 = Bus317()
bus02 = Bus317()
#打印类和实例的内存:类和实例化都有单独的命名空间
print(id(Bus317),id(bus01),id(bus02))
#查看对象的属性或方法
print(dir(bus01))
print(bus01.linE)
bus01.run(0)
bus02.run(1)
#直接用类访问属性
print(Bus317.linE)
实例化对象的构造方法,实例化对象的时候会自动调用__init__方法
用来初始化属性
class Bus317(object):
# 类属性
# line-->公共属性
line = "317"
def __init__(self,pro):
print("this is __init__")
self.pro1 = pro
# cls接收到的参数就是当前类(Bus317)
def __new__(cls, *args, **kwargs):
print("this is new method")
return "new"
# return object.__new__(cls)
# 返回父类object.__new__方法通过当前类创建的对象
# *args和 ** kwargs主要用于函数定义。你可以将不定数量的参数传递给一个函数。
# 这里的不定的意思是: 预先并不知道, 函数使用者会传递多少个参数给你, 所以在这个场景下使用这两个关键字。
def run(self,flag):
print("bus317 is run")
if flag == 0:
print("从农大到长华小区")
else:
print("从长华小区到农大")
# 创建实例
bus01 = Bus317("benci","chao")
bus02 = Bus317("futian")
print(bus01)
# print(dir(bus01))
# print(bus01.pro1,bus02.pro1)
# 查看类空间有什么东西
# print(Bus317.__Dict__)
# 查看实例空间有什么内容
# print(bus01.__Dict__)
__init__是对创建好的实例c;进行初始化工作的方法
__new__是创建实例的方法
1.__new__方法必须传入一个参数(cls)c;代表当前类
2.__new__必须返回一个实例化的对象
3、__init__的self就表示__new__返回的实例c;__init__对这个实例进行初始化工作
4、子类没有__new__c;会去找父类的__new__
5、新式类才有__new__
6、如果实例化对象和本身class不一致c;__init__不会执行
创建一个学生类
• 类名:student
{'yuwen':100, 'suxue':100, 'yinyu':100}
• 方法:求总分、求平均值
class student(object):
school = "hunau"
def __init__(self,name,age,scores):
# 初始化函数c;self-->实例本身
self.name = name
self.age = age
self.school = student.school # 使用类属性
self.scores = scores
def sum(self):
# sum1 = 0
# for i in self.scores.values():
# sum1 += i
# return sum1
# 方法二
return sum(self.scores.values())
def avg(self):
# avg1 = self.sum()/len(self.scores)
# return avg1
# 方法二
return self.sum()/len(self.scores)
lzc = student("lzc", 20,{"math":100,"Chinese":90})
lzw = student("lzw", 20,{"math":98,"Chinese":92})
llf = student("llf", 20,{"math":97,"Chinese":91})
print(lzc.sum())
print(lzc.avg())
类的实例方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称
在调用这个方法的时候你不为这个参数赋值c;Python会提供这个值
这个特别的变量指对象本身c;按照惯例它的名称是self
class A:
NAME = "sc"
age = 4
def info(self,seX):
print(f"我是:{self.namE},今年{self.agE}岁c;性别{sex}")
print(self)
print(id(self))
def info2(chao):
print(f"this is {Chao}")
#self 表示实例本身
a = A()
print(id(a))
a.info("man")
print("***")
A.info(a,"man") # 实际上运行
#输出结果:
1889166028752
我是:sc,今年4岁c;性别man
<__main__.A object at 0x000001B7DB11EFD0>
1889166028752
self 不必非写成selfc;self的名字不是强制规定的(可以理解为不一定要命名为self)
最好还是尊重约定俗成的习惯c;使用self
b = A()
b.info2()
#输出结果:
this is <__main__.A object at 0x00000278DEEEEFD0>
方法中可以不传入selfc;如果不写的话就不能使用对象调用
实例调用方法的时候c;默认就会把当前的实例传给selfc;不需要手动传入
示例:
class Parent:
def pprt(self):
print(self)
class Child(Parent):
def cprt(self):
print(self)
c = Child()
c.cprt()
c.pprt()
#输出结果:
<__main__.Child object at 0x00000278DEEEEFA0>
<__main__.Child object at 0x00000278DEEEEFA0>
用类实现斐波那契数列的运算(编写自定义迭代器)
斐波那契数列: 0 1 1 2 3 5
代码如下
class Fib_list:
def __init__(self):
self.before = 0
self.now = 1
def __iter__(self):
return self
def __next__(self):
result = self.now
self.before,self.now=self.now,self.before+self.now
return result
a = Fib_list()
print([next(a) for i in range(11)])
面向对象的编程带来的主要好处之一是代码的重用c;实现这种重用的方法之一是通过继承机制。
继承完全可以理解成类之间的类型和子类型关系。
• 衍生出不同的子类c;大部分代码一样c;部分代码不一样
• 继承父类的属性和方法
• 对象属性查找
先在实例空间查找c;没有就去类空间
再没有就去父类空间找c;层层往上递归查找
class Animal():
species = "Animal"
count = 0
def __init__(self):
self.name = "animal"
Animal.count += 1
print("初始化animal......")
def breath(self):
print("i can breath")
def eat(self):
print("i can eat")
# 继承Animal类
class Person(Animal):
species = "Person" #重写父类属性
class Dog(Animal):
species = "Dog"
def __init__(self): #重写父类的__init__
print("i am dog")
def eat(self): #重写父类的eat()
print("dog is eatTing......")
class Pig(Animal):
count = 0 #重写父类属性
def __init__(self): #重写父类__init__
self.name = "pig"
Pig.count += 1
print("初始化Pig......")
super().__init__() #去执行父类的__init__,子类访问父类属性的方法属性
print(Animal.count)
# 输出结果
0
# 实例化Animal
animal = Animal()
print(Animal.count,animal.count)
# 输出结果
初始化animal......
1 1
# 实例化Person
person = Person()
print(person.species,person.count,Person.count)
#输出结果
初始化animal......
Person 2 2
# 实例化Dog
dog = Dog()
print(dog.count)
print("*"*5)
# 输出结果
i am dog
2
# 实例化Pig
pig = Pig()
print(pig.count,pig.Name)
# 输出结果
初始化Pig......
初始化animal......
1 animal
# 类与实例的关系
print("类与实例的关系".center(30,"*"))
print(type(dog))
print(isinstance(dog,Dog), isinstance(dog, Animal))
# 输出结果
***********类与实例的关系************
<class '__main__.Dog'>
True True
• 增加了代码的利用率c;如果需要给Pig/Person同时增加新的功能时c;只需要在Animal中添加即可
• 便于更新迭代c;如果你的父类方法的功能不能满足你的需求c;你可以在子类重写你父类的方法父类里的方法
python不支持多态c;语法上的多态c;不需要额外实现多态代码
python里处处都是多态,python是一个多态类型语言c;本身就实现了多态c;崇尚鸭子类型
在鸭子类型中c;关注的不是对象的类型本身c;而是它是如何使用的。
多态的好处
• 增加了程序的灵活性
• 以不变应万变c;不论对象千变万化c;使用者都是同一种形式去调用c;如func(animal)
• 增加了程序额可扩展性
• 通过继承animal类创建了一个新的类c;使用者无需更改自己的代码c;还是用func(animal)去调用
• 多态:同一种事物的多种形态c;动物分为人类c;猪类(在定义角度)
• 多态性:一种调用方式c;不同的执行效果(多态性)
• 实现接口重用
自定义异常类
• 自定义异常能让异常更精准
• 自定义异常类:当list内元素长度超过10的时候抛出异常
• 自定义异常类:消息小于8时抛出异常
方法一
class List_Error(Exception):
pass
lst1 = [1,2,3]
if not 8<len(lst1)<10:
raise List_Error("列表长度小于8或超出10")
else:
print("No Problem")
方法二:
class List_Error(Exception):# 注:继承Exception的基类
def __init__(self,lst,messagE):
self.lst = lst
self.message = message
def __str__(self):
str1 = "list is " + str(self.lst)
str1 = str1 +"n" + self.message
return str1
try:
lst = [1,2,3,4,5,6]
if not 8 < len(lst) < 10:
raise List_Error(lst,"列表长度小于8或超出10!")
except List_Error as e:
print("listError error:",E)
以上是大佬教程为你收集整理的Python——什么是面向对象?类的定义、self和继承详解全部内容,希望文章能够帮你解决Python——什么是面向对象?类的定义、self和继承详解所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。