十九、面向对象的定义,及基础语法
一、什么是面向对象
面向对象编程思想 OOP
面向对象是一种编程思想,是前辈们总结出的经验,指导程序员如何编写出更好的程序 ,
核心是对象,程序就是一系列对象的集合, 程序眼负责调度控制这些对象来交互着完成任务:
案例:1 把大象装进冰箱 ?
面向过程:
1.打开冰箱
2.装入大象
3.关闭冰箱
面向对象:
找个具备装大象的技能的对象
在面向对象中程序员的角度发生改变,从具体的操作者变成了指挥者;
强调:对象不是凭空产生的,需要我们自己设计
案例:
西天取经
如来有一堆破书要传出去,他没有自己干,而是找了五个对象帮他去干,
如来只要负责控制调度的对象即可 ,
如果某个对象发生变化,也不会影响其他的对象 , 扩展性
案例:
曹操吟诗
喝酒吃肉,人生真爽
喝酒吃肉,人生几何
对酒当歌,人生几何
### 面向对象的三大优点
1.扩展性
2.灵活性
3.重用性
### 缺点:
1.程序的复杂度提高了
2.无法准确预知结果
### 使用场景
对扩展性要求较高的程序 ,通常是直接面向 用户的,例如:qq,微信
# 面向过程编程思想
关注的核心是过程,过程是就是一步一步的执行步骤,既先干啥在干啥
优点:逻辑清晰 , 复杂问题简单化,流程化
缺点: 扩展性差,可维护性差
使用场景:
对扩展性要求较低的程序例如:系统内核,git,计算器
记住:不是所有程序都要面向对象,得分析具体需求
# 类和对象
这是OOP中的最核心的两个概念
## 类
既类型,类别 ,是一种抽象概念
是一系列具备相同特征和相同行为的对象的集合
### 对象
就是具体存在的某个事物,具备自己的特征和行为
对象就是特征和技能的结合体
### 类和对象的关系
类包含一系列对象
对象属于某个类
在生活中是先有对象再有类
而在程序中是先有类才能有对象,我们必须先告诉计算机这类的对象有什么特征有什么行为
总结出一个结论:在使用面向对象编程时,第一步就是思考需要什么样的对象,对象具备什么样的特征和行为,从而根据 这些信息总结出需要的类型
# 创建类和对象
定义类的语法
```python
class 类的名称:
# 类中的内容 描述属性和技能
#描述属性用变量
#描述行为用函数
#类名称 书写规范 首先是见名知意 名称是大驼峰命名法
#驼峰就是单词首字母大写 , 大驼峰是第一个字母大写,小驼峰是第一个字母小写
```
创建对象的语法:
```python
class Person:
pass
#创建对象
p = Person()
```
属性的写法:
```python
属性可以写在类中
类中的属性,是所有对象公共的
也可以写在对象中
对象中的属性,是每个对象独特的(不一样的)
如果类中和对象中存在同样的属性,先访问对象 如果没有在访问类
class Person: # 定义一个类 country = "China" # 定义一个类变量 def __init__(self, *args): # 初始化方法,self是对象,是一个必须传的参数 self.name = args[0] # 公有变量 self.hp = args[1] self.age = args[2] self.sex = args[1] def walk(self, n): # 成员方法,一般情况下必须传参数,且必须写在第一位 print("%s走走走,走了%d步" % (self.name, n)) # self.name调用成员变量 # 创建一个对象,或者是Person实例化alax alex = Person("狗蛋", "100", "18", "女") alex.walk(100) # 调用成员方法,并传值 print(Person.country) # 调用类变量 Person.country = "台湾" # 修改类变量值 print(Person.country) # 需求计算圆的面积和周长 pi = 3.14 class Circular: # 定义一个圆类 def __init__(self, r): self.r = r # 面积 def area(self): areas = pi * self.r ** 2 return areas # 周长 def girth(self): girths = self.r * pi * 2 return girths a = Circular(10) res1 = a.area() res2 = a.girth() print(res1, res2)
```
属性的增删改查
```python
增加属性
对象变量名称.属性名称 = 属性值
删除属性
del 对象的变量名称.属性名称
修改
对象.属性 = 新的值
查看属性 访问的是对象的所有属性
print(对象.__dict__)
访问对象的类信息
print(对象.__class__)
```
# init方法
叫做初始化方法,本质上就是一个函数
特点1: 当实例化 对象时,会自动执行init方法
特点2:会自动将对象作为第一个参数传入,参数名称位self ,self可以是别的名字,但不建议改
功能:用户给对象赋初始值
#方式一、为对象初始化自己独有的特征 class People: country='China' x=1 def run(self): print('----->', self) # 实例化出三个空对象 obj1=People() obj2=People() obj3=People() # 为对象定制自己独有的特征 obj1.name='egon' obj1.age=18 obj1.sex='male' obj2.name='lxx' obj2.age=38 obj2.sex='female' obj3.name='alex' obj3.age=38 obj3.sex='female' # print(obj1.__dict__) # print(obj2.__dict__) # print(obj3.__dict__) # print(People.__dict__) #方式二、为对象初始化自己独有的特征 class People: country='China' x=1 def run(self): print('----->', self) # 实例化出三个空对象 obj1=People() obj2=People() obj3=People() # 为对象定制自己独有的特征 def chu_shi_hua(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male' obj.name = x obj.age = y obj.sex = z chu_shi_hua(obj1,'egon',18,'male') chu_shi_hua(obj2,'lxx',38,'female') chu_shi_hua(obj3,'alex',38,'female') #方式三、为对象初始化自己独有的特征 class People: country='China' x=1 def chu_shi_hua(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male' obj.name = x obj.age = y obj.sex = z def run(self): print('----->', self) obj1=People() # print(People.chu_shi_hua) People.chu_shi_hua(obj1,'egon',18,'male') obj2=People() People.chu_shi_hua(obj2,'lxx',38,'female') obj3=People() People.chu_shi_hua(obj3,'alex',38,'female') # 方式四、为对象初始化自己独有的特征 class People: country='China' x=1 def __init__(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male' obj.name = x obj.age = y obj.sex = z def run(self): print('----->', self) obj1=People('egon',18,'male') #People.__init__(obj1,'egon',18,'male') obj2=People('lxx',38,'female') #People.__init__(obj2,'lxx',38,'female') obj3=People('alex',38,'female') #People.__init__(obj3,'alex',38,'female') # __init__方法 # 强调: # 1、该方法内可以有任意的python代码 # 2、一定不能有返回值 class People: country='China' x=1 def __init__(obj, name, age, sex): #obj=obj1,x='egon',y=18,z='male' # if type(name) is not str: # raise TypeError('名字必须是字符串类型') obj.name = name obj.age = age obj.sex = sex def run(self): print('----->', self) # obj1=People('egon',18,'male') obj1=People(3537,18,'male') # print(obj1.run) # obj1.run() #People.run(obj1) # print(People.run)
练习:创建一个类具备几个属性,通过初始化方法来给他设置属性
```python
class Dog:
def __init__(self,kind,color,age):
self.kind = kind
self.color = color
self.age = age
d1 = Dog("二哈","黑白",1)
d1 = Dog("泰迪","棕色",2)
注意:该函数不能有任何返回值/.... 只能是None 规定如此..
```
对象的精髓就是讲数据和处理数据的函数整合到一起 ,这样一来拿到一个对象就同时拿到了需要处理的数据以及处理数据的函数
## 对象的绑定方法
默认情况下类中的方法都是对象绑定方法
其特殊之处在于,
当使用对象调用该函数时会自动传入对象本身,作为第一个参数
当使用类名来调用时他就是一个普通函数,有几个参数就得传几个参数
练习:写一个学生类,具备一个打招呼的技能 要能输出自己的名字信息
```python
class Student:
def __init__(self,name):
self.name = name
def say_hi(self):
print("hello my name is %s" % self.name)
```
## 类绑定方法
类绑定方法用@classmethod来装饰
特殊之处:不管用类还是对象调用,都会自动传入类本身,作为第一个参数
什么时候绑定给对象:当函数逻辑需要访问对象中的数据时
什么时候绑定给类:当函数逻辑需要访问类中的数据时
# 非绑定方法
或叫做静态方法,就是即不需访问类的数据,.也不需要访问对象的数据
语法:@staticmethod
不常用
class OldBoyStudent: school = "oldboy" def __init__(self, name, hp): self.name = name self.hp = hp def read(self): # 对象绑定方法 print("%s学生,在读书!" % self.name) @classmethod # 类绑定方法,也叫静态方法,需要访问类属性数据,不可以访问对象属性 def show_school(cls): # print(self.school) print(cls.school) @staticmethod # 非绑定方法,不要访问对象属性数据,也不要访问类属性数据,就是一个普通函数,在上面加上@staticmethod def print_hello(): print("hello world") stu = OldBoyStudent("鸡哥", 100) print(OldBoyStudent.school) # oldboy 访问类属性,或静态属性的值 print(stu.__dict__) # {'name': '鸡哥', 'hp': 100} 访问的对象的所有属性 print(stu.__class__) # <class '__main__.OldBoyStudent'> 访问的是对象类的信息 stu.read() stu.show_school() # 类访问 stu.print_hello() # 普通函数 # OldBoyStudent.show_school(stu) # OldBoyStudent.show_school() # print(OldBoyStudent) # stu = OldBoyStudent("jack") # stu.show_school() # # OldBoyStudent.print_hello() # stu.print_hello()