面向对象
编程范式
面向对象指的是一种编程范式;
编程范式:可以理解为一种编程方式,编程规范,编程模式
- 面向过程
面向过程编程:是一种以过程为核心的编程,主要是在解决一个问题的时候 , 将这个问题拆分成一个个小步骤完成并且拼接起来的就是面向过程。
- 面向对象
面向对象编程(object oriented programming ,简称OOP):是一种以对象为核心的编程 , 面向对象在解决问题的时候是思考如何设计这个事情。
类和对象
-
在代码里面实行一个对象是通过类进行产生的;
-
类就相当于生活中的一个类别,一个比较抽象的概念。
-
对象就是一个通过类产生的一个拥有属性以及行为的实体,是对应类里面的一个个体
-
<先有类 , 再有对象>
- 函数是一系列的指令,完成特定的功能。变量是描述事物特征的东西,姑且叫信息。
- 类就是将变量信息和函数指令结合到一起的东西。变量表达类的特征(属性),函数表示类的功能(方法)。
- 对象是类的特例。犹如动物和人的关系。
类的定义
python中如何定义一个函数
# 定义 def 函数名(形参): 函数体 # 调用 函数名(实参) def func_1(name): return f'{name}是个超人' print(func_1('伤心超人'))
python中定义类的语法:
class 类名: 代码
类目的定义:使用驼峰式命名(大驼峰,每个单词的首字母大写)
定义类之后 , 执行代码 , 类里面的代码也会一起执行
定义再类中的变量称之为属性
class People: ''' 我是类文档 就相当于类的说明书 ''' # 类属性 (所有对象共有的) height = 1.73 weight = 200 # 实例化类 xs = People() print(xs.weight) # print(People.__dict__) mj = People() # 创建对象独有的属性,如果属性存在,则是修改属性值的操作 # 对象名.属性名 = 属性值 mj.weight = 90 mj.weight = 85 print(mj.weight) # 使用对象.__dict__得到的是对象的属性 print(mj.__dict__) # 修改类属性 # 类名.属性名 = 属性值 People.weight = 170 print(xs.weight) # 动态的增加类属性 People.age = 20 print(xs.age)
--init--
class Animal: '''动物类''' # 初始化方法 def __init__(self , name , age): # 属性 self.age = age self.name = name cat = Animal('da' , 1) print(cat.name) print(cat.age) dog = Animal('xi',1.5) print(dog.name)
self
class Animal: '''动物类''' # 初始化方法 def __init__(self , name , age): # 属性 self.age = age self.name = name def sleep(self): print(f'{self.name}睡觉') cat = Animal('da' , 1) dog = Animal('xi',1.5) dog.sleep() # print(cat.name) # print(cat.age) # print(dog.name)
封装
面向对象的三大特性:封装、继承、多态
-
封装:把功能代码 , 数据封装到某一个地方,需要的时候进行调用 , 提过程序的安全性。即把属性以及方法放到类中 ,通过类对象的操作或者调用。
-
通过封装,可以将一些不想给用户看到的功能进行隐藏 , 用户只能访问公开的功能,可以提高数据的安全性 , 也对后期的维护降低成本。
-
封装的好处:便于分工 , 便于复用 , 可扩展性强。
class People: '''人类''' height = 1.73 weight = 200 # 初始化方法 def __init__(self , name , age , weight , job): self.name = name self.age = age self.weight = weight self.job = job def eat(self): print(f'{self.name}食べる') self.weight += 2 def drink(self): print(f'{self.name} 飲みましょう。') self.weight += 0.5 def run(self): print(f'{self.name} gogogo') self.weight -= 0.5
属性查找
-
在实例化属性中不同的对象 , 调用的属性不会产生影响互不干扰
-
对象寻找对应的属性,先从自身的实例属性开始查找 , 如果没有再从类属性查找。
-
不同的对象之间的实例属性是互不相通 , 都是独有的 , 两者无法相互访问
class Cat: # 类属性 category = 'ねこ' age = 2 # 初始化方法 def __init__(self , name , category): # 实例属性 self.name = name self.category = category def sleep(self): print(f'{self.name}睡觉') mao1 = Cat('xiaopang' , '家猫') mao1.age = 1 print(mao1.name) print(mao1.category) mao2 = Cat('dapang','流浪猫') print(mao2.name) print(mao2.age) # 2 print(mao2.category)
属性隐藏
在类中定义一些数据或者功能不希望被外部访问到以及操作的时候 , 可以将数据以及功能进行隐藏。
在Python中没有绝对的隐藏 , 是可以通过一些方法对其进行访问的。
在类中的三种隐藏方法:
- 属性或者方法名前加上双下划线
- 使用property()函数
- @property 装饰的方法是获取属性值的方法 , 被装饰的方法的名字会被作为属性名 , 方法名尽量跟隐藏的属性名一致
@属性名.setter 装饰的方法是设置属性值的方法
@属性名.deleter 装饰的方法是删除属性值的方法
属性或者方法名前加上双下划线
双下划线开头的属性 , 是对象的隐藏属性,隐藏属性可以在类内部进行访问
class People: def __init__(self , name , age): self.name = name self.__age = age # 将age属性进行隐藏 def __speak(self): print(f'我今年{self.__age}') hh = People('haha', 24) # print(hh.name) # 获取对象属性 # print(hh.__dict__) # 对象名称._类名__属性名 print(hh._People__age) hh._People__speak()
使用property()函数
property可以设置、获取 , 删除对象的某一个属性值 , 也可以限制用户对属性的设置与获取
# property 属性 # property(fget = None , fset = None , fdel = None , doc = None) # fget = 是获取属性值的方法 # fset = 是设置属性值的方法 # fdel = 是删除属性值的方式 class People: def __init__(self , name , age): self.name = name self.__age = age # 将age属性进行隐藏 def speak(self): print(f'我今年{self.__age}') def get_age(self): print('===get=====') return self.__age def set_age(self , value): print('===set=====') self.__age = value def del_age(self): print('===del=====') del self.__age # 赋予对象属性权限 加上这句话,可以限制权限,而且对象进行操作很符合习惯 age = property(fget=get_age , fset=set_age , fdel=del_age) p2 = People('小小怪', 26) print(p2.name) # 获取对象属性 print(p2.__dict__) # 对象名称._类名__属性名 print(p2._People__age) # ac._People__speak() # 'People' object has no attribute '_People__speak' # 因为本来就没有__speak,如果没有property,speak可以直接调用 print(p2.age) p2.age = 22 print(p2.age) del p2.age # 如果没有property,删除就得是p2.del_age,和习惯不同 print(p2.__dict__)
装饰器
class Student: def __init__(self): self.__name = '开心超人' @property # grade = property(grade) 不清楚具体咋实现的,但是结果是 将函数的返回值 __name 赋给grade,也就是下变函数的名字,所以说为了让外边调用方便还是不要瞎起名 def grade(self): return self.__name @grade.setter def grade(self , value): self.__name = value @grade.deleter def grade(self): del self.__name p5 = Student() print(p5.grade) p5.grade = "花心超人" print(p5.grade) del p5.grade # print(p5.grade)
继承
- 在python中是在多个类中的一种所属关系
- 被继承的类称为父类
- 接收的类称为子类
- 在继承中子类是默认继承父类中的属性以及方法
- 继承可以解决类与类之间的代码冗余。
- 在python3中都会默认继承object类 , 即object是python中所有类的父类(基类 , 超类)。
单继承
一个子类继承一个父类 , 子类默认继承父类中的所有方法 , 属性
class Father: def __init__(self , name): self.name = name self.clothes = '👚' self.job = '工作' def eat(self): print('吃') return '吃东西' class Son(Father): pass p3 = Son('校长') print(p3.name) print(p3.clothes) print(p3.job) print(p3.eat())
重写
在子类中重新定义父类的方法 , 子类在实例化之后会默认的访问自身的方法。
class Father: def __init__(self , age , name='孙悟空'): self.name = name self.age = age def eat(self): print(f'{self.name}偷吃亚奇罗贝 的 <・)))><<') def money(self): print('1万') class GrilOfSon(Father): def eat(self): print(f'{self.name}在优雅的吃饭') # super() def money(self): print('5千') # 方法一,指出父类名 需要self Father.money(self) # 方法二 , 通过super() 不用self super().money() p4 = GrilOfSon('小芳' , 8) p4.eat() p4.money()
属性查找:子类对象自身——>子类中——>父类中
多层继承
被继承类都有属于自己的父类
class A: name = '1A' name1 = '11A' class B(A): name = '2B' name2 = '22B' class C(B): name = '3C' name3 = '33C' def __init__(self): self.name = '百事通' q = C() print(q.name) # 如果没有初始化就会查到C类的name; # 如果C类没有name,就会查到B类的name;以此类推 # 可以将前辈的东西都继承了,人要是天生就继承就好了 print(q.name1) print(q.name2) print(q.name3) # 只能查到初始化方法里的属性 print(q.__dict__)
多继承
多继承:一个子类有多个父类
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法
class Horse: def body(self): return '健壮' class Donkey: def body(self): return '娇小' def labour(self): return '勤快能干' class Mule(Horse , Donkey): pass M = Mule() print(M.body()) # 健壮 print(M.labour()) # 勤快能干 # 查看继承的顺序 print(Mule.__mro__) # 查看第一个父类 # print(Mule.__base__) # 在多继承中查看所有的父类,查不到爷爷类 print(Mule.__bases__) # (<class '__main__.Mule'>, <class '__main__.Horse'>, <class '__main__.Donkey'>, <class 'object'>) # <class '__main__.Horse'> # (<class '__main__.Horse'>, <class '__main__.Donkey'>)
多态
不同的对象, 调用同一个方法 , 表现出不同的形态。
多态的实现:1、必须要有类的继承;2、子类对父类的方法进行重写
class A: def func(self): print('狗叫') class B(A): def func(self): print('猫叫') a = A() b = B() a.func() b.func()
检查类型
# type() # 检查单个的数据类型 # issubclass(cls , class_tuple) # 检查类是否为后者的子类(检查前者是否继承后者) # isinstance(obj , cls) # 检查 对象 是否为类中的 res = 'jjjj' print(isinstance(res , int)) # False print(issubclass(str, object)) # True class Father: pass h = Father() print(isinstance(h, Father)) # True print(isinstance(res, Father)) # False class Son(Father): pass print(issubclass(Father, Son)) # False print(issubclass(Son, Father)) # True
_str_
str 是一个类的方法,在打印类对象,获取其属性信息时调用。
打印一个实例化对象时,默认打印的其实时一个对象的地址,
但是我们可以对其进行重载,打印我们想要的信息。
class people: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '这个人的名字是%s,已经有%d岁了!'%(self.name,self.age) a=people('孙悟空',999) print(a) # 这个人的名字是孙悟空,已经有999岁了! # 如果没有重载函数的话输出的就是一串看不懂的字符串: # <__main__.people object at 0x00000272A730D278
_del_
当检测到对象没有在继续引用时 , 就会自动的将对象所占用的内存空间清除
class Person: def __init__(self, name): self.name = name def __str__(self): return f'{self.name}来了 ' def __del__(self): print(f'{self.name}被清除') cx = Person('粗心超人') tx = Person('甜心超人') print(cx) del cx print('=' * 20) print(tx) print('kaijiu')
绑定与非绑定
类方法(绑定)
- 通过@classmethod进行方法装饰
- 类方法操作的是类属性 , 同cls进行对类的绑定
- 类方法和对象方法(实例方法)都是绑定的
# 类方法(绑定) class Student: # 类属性 number = 0 # 实例属性 def __init__(self , name): self.name = name # 实例化的时候会执行下边的count函数,数量加一, # 每次创建对象就会被监测到,而且给他编个号 self.id = self.count() @classmethod def count(cls): cls.number += 1 return cls.number ddg = Student('大大怪') print(ddg.number) xxg = Student('小小怪') print(ddg.number) print(Student.number) print(ddg.id) print(xxg.id)
静态方法(非绑定)
- 通过@staticmethod进行方法装饰
- 不需要绑定self以及call
- 静态方法与定义在类外面的函数是一致的
- 只是放在类中 ,方便管理(维护)。
import time class FanPai: def __init__(self, name): self.name = name @staticmethod def str_time(): print(f'{time.strftime("%Y/%m/%d")}') ddg = FanPai('大大怪') xxg = FanPai('小小怪') # 类和对象都可以 调用 # 类里边的的静态方法类似于模块里的函数 ddg.str_time() xxg.str_time() FanPai.str_time()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)