文章总览图
本文简介
- 面向对象编程--类的创建
- 面向对象编程--继承与初始化函数
- 面向对象编程--类的封装与复用
类的语法
类是个抽象的概念:例如大佬类,小白类。类的划分标准:写代码的人来定。
例如:
my only 大佬类里面的一个具体大佬
monica 小白类里面一个具体的小白
Python 类的语法
1.关键字是class
。写法结构是class
类名:
2.类名的规范是: 1 数字字母下划线组成 2 不能以数字开头 3 首字母大写,驼峰命名 (例如:TestResult
)
3.类属性。例如a=1
放在类里面的变量值。
4.类方法/类函数:就是写在类里面的函数。类函数/类方法:类函数就是类方法。函数以 def
开头。写法结构是def
函数名(参数):
5.类函数定义:写在类里面就是类函数。
代码语言:javascript复制'''
男朋友类 女朋友类
理想的女朋友标准是什么?
长发 温柔 大长腿 学历 工作 3-5 测试经验 会自动化
理想的男朋友的标准是什么?
体贴 有钱 175 绅士 温柔 会做饭 会赚钱
'''
class BoyFriend:#男朋友的模板 BoyFriend 就是类名
类属性:
height=175
weight=130
money="500万"
def print_msg(self):#self 是实例本身 self 是固定的占坑符号 类里面的方法都必须带 self 这个参数
print(self) #这里 self 是实例本身,这里实例就是 BoyFriend()
def cooking(self): #会做饭 self
print(self)
print("男朋友要会做饭!")
def earn(self): #会挣钱
print("男朋友月薪是 3 万!")
1.实例也就是对象。实例就是个具体的1个例子。类名()
例如:BoyFriend()
2.怎么去创建一个实例/对象?类名()
bf=BoyFriend()
print(bf)
print("*"*20)
#print("*"*20) #print 表示自动换行
bf.print_msg() #调用方法/函数
print(bf.money) #调用属性
1.实例具有类里面的所有属性和方法的使用权限。
2.实例可以调用类里面的任意属性,实例可以调用类里面的任意函数/方法。
3.调用属性:实例名.属性名
4.调用方法/函数:实例名.方法名()
实例名.函数名
函数名和方法名是一个东西,叫法两种。
5.普通函数和类函数区别:类函数有个self
QA类
写一个软件测试工程师类,要求有属性有函数,并完成属性和函数的调用。
代码语言:javascript复制class SoftwareQAEngineer:
#类属性
title='QA'
age='20-35'
experience='2-3年'
salary='1.5w'
#函数
def test_function(self):#例如 test_function()本身的作用是输出后面的“我会功能测试”
#print("我会功能测试")
return("我会功能测试")
def test_api(self):
print("我会接口测试")
def major(self):
print("计算机科学与技术")
def test_auto(self):
print("我会自动化测试")
qa=SoftwareQAEngineer()
#属性调用
print("测试工程师的年龄是:",qa.age)
print("测试工程师的经验要求:",qa.experience)
print("测试工程师的薪资待遇:",qa.salary)
print(qa.title)
#函数调用
qa.major()
qa.test_api()
qa.test_auto()
qa.test_function()
'''
输出:
测试工程师的年龄是:20-35
测试工程师的经验要求:2-3年
测试工程师的薪资待遇:1.5w
QA
计算机科学与技术
我会接口测试
我会自动化测试
我会功能测试
'''
print(qa.test_function())
输出:#None
问题分析:
test_function()
本身的作用是输出“我会功能测试”到这个控制台。print
已经输出了,再次使用print(qa.test_function())
进行输出,已经没有值可以输出了,所以输出None
。
print
和return
的区别:
如果把print("我会功能测试")
改为return("我会功能测试")
。
return
是当你调用这个函数的时候,它会返回一个值,返回return
。后面的这个值"我会功能测试",当我使用print(qa.test_function())
的时候,会返回到控制台。
类与对象
1.类的概念:具有某一类共同属性和特性的事物。
2.类一般包含属性和方法。
3.类可以包含属性和方法。也可以不包含属性和方法。
代码语言:javascript复制class Teacher:#不包含属性和方法
pass
代码语言:javascript复制class Teacher:
name="小红"
age="25"
def coding(self):#函数里面第一个参数是self,就是实例方法。
#print("会敲代码")
print(self.name "会敲代码")
def cooking(self):#函数里面第一个参数是self,就是实例方法。
# print("会做蛋炒饭")
print(self.name "会做蛋炒饭")
@classmethod #类方法
def swimming(cls):#cls 就是类本身。
print("老师还要会游泳")
@staticmethod#静态方法
def sing():#不用传任何参数,就是个普通函数。
print("要会唱歌")
t=Teacher()#实例,隐式的传递。
t.cooking()#隐式的传递。
Teacher.coding(t)#显示的传递,不建议使用。
Teacher.sing()#类名调用。
t.sing()#实例调用。
'''
输出:
会做蛋炒饭
会敲代码
要会唱歌
要会唱歌
老师还要会游泳
老师还要会游泳
'''
Teacher.swimming()
t.swimming()
1.Teacher.coding()
报错:TypeError: coding() missing 1 required positional argument: 'self'
提示:缺少一个位置参数self
。
Teacher.coding(self)
报错:NameError: name 'self' is not defined
2.self
必须传的是实例本身,如果创建实例的话,它就会默认把这个实例传到self
这个位置。
如果直接类名.coding()
就会报错。把实例传进去,变为Teacher.coding(t)
就可以了。
类中的3种方法
1.实例方法:
意味着这个方法只能实例来调用。
实例 Teacher()
类 Teacher
2.类方法:
@classmethod
调用类方法:Teacher.swimming()
t.swimming()
类方法的调用:不创建实例,创建实例,都可以调用。
3.静态方法:
@staticmethod
调用静态方法:Teacher.sing()
t.sing()
- 总结:实例方法self,类方法cls,静态方法就是(普通方法)
- 共同点:三种方法都可以通过实例和类名调用。
- 不同点:类方法和静态方法,不可以调用类里面的属性值。如果你要参数,请自己传递参数。
1.什么时候去定义静态和类方法呢?
当你的某个函数与其它的函数没有任何关系的时候,就可以定义为静态方法和类方法。
静态方法和类方法只是为了方便调用,不需要创建实例,直接类名.函数名
就可以完成调用。
class AppleTeacher:
def_init_(self,name,age=23):#初始化函数 这是个实例方法 初始化函数可以有默认值。一般不传动态参数和关键字参数。
#外面的属性值变成里面的,就加 self 赋值。此处关键字参数是 age=23。
self.name=name
self.age=age
self.height=168
#初始化函数没有返回值,不要写 return。
# 错误写法:
# def _int_(self):#这个不是初始化函数。
# pass
def love_singer(self,love_singer):
return(self.name "喜欢的歌手是{0}".format(love_singer))
def coding(self,lines,language="Python"):#函数里面第一个参数是 self 就是实例方法。
# 这里的 language 是形参。"Python"是默认参数。位置参数 lines 要放在默认参数之前。
#print("会敲代码")
print(self.name "会敲{0}代码,写了行{1}代码".format(language,lines))
def cooking(self,*args):#函数里面第一个参数是 self 就是实例方法。
#动态参数*args。
for item in args:#动态参数包含 0 个或多个,不计数。
# print("会做蛋炒饭")
print(self.name "会做{0}".format(item))
def teacher_info(self,*args):
self.cooking(*args)
print("{0}老师,今年{1}岁,身高{2},可以嫁人了!".format(self.name,self.age,self.height))
# @classmethod #类方法
# def swimming(cls):#cls 就是类本身,可在第一个参数 cls 后面加参数。
# print("老师还要会游泳")
# @staticmethod#静态方法
# def sing(name):#不用传任何参数 就是个普通函数
# print("要会唱{0}".format(name))
'''
初始化函数
1.错误写法:
t1=AppleTeacher()
TypeError: _init_() missing 2 required positional arguments: 'name' and 'age'
2.什么时候用初始化函数?
想用就用,不想用就不用。
规律:如果某个属性值是多个函数共用的,就可以用初始化函数。
'''
# t1=AppleTeacher("清菡","25")
# t2=AppleTeacher("毛毛")
# t1.coding(1000)#在这里给位置参数 lines 赋值,位置参数是没有默认值的
# t1.cooking('蛋炒饭','小炒肉','方便面')
# print(t1.love_singer("萧亚轩"))
# t1.sing("邓丽君的《你怎么说》")
# t2.teacher_info()
t3=AppleTeacher("星星")
t3.teacher_info("多宝鱼","鲈鱼")
# t2=AppleTeacher("张三","22")
# t3=AppleTeacher("李四","20")
# t4=AppleTeacher("王五","18")
# t1.swimming()
# t2.cooking()
# t3.coding()
# t4.sing()
总结:不管是类方法,静态方法和实例方法,它的函数和普通函数一模一样的, 无区别。类方法,静态方法和实例方法的参数传递和return
这些无区别。
继承
代码语言:javascript复制class RobotOne:#第一代机器人
def _init_(self,name,year):
self.year=year
self.name=name
def walking_on_ground(self):
print(self.name "只能在平地行走,有障碍物就会摔倒。")
def robo_info(self):
print("{0}产生的机器人{1},是中国研发的".format(self.year,self.name))
#继承
# class RobotTwo(RobotOne):#第二代机器人继承于第一代机器人的类。
# def walking_on_ground(self):#子类里面的函数名与父类里面的函数名重复的时候就叫重写。
# print(self.name "可以在平地上平稳地行走")
#def walking_avoid_block(self):#继承下面,这个是拓展。
#我想在子类的一个函数里面,调用父类的一个函数。
# self.robo_info()
# print(self.name "可以避开障碍物")
#为了多继承写的第二代机器人
class RobotTwo():#第二代机器人继承于第一代机器人的类。
def _init_(self,name):
self.name=name
def walking_on_ground(self):#子类里面的函数名与父类里面的函数名重复的时候就叫重写。
print(self.name "可以在平地上平稳地行走")
def walking_avoid_block(self):
print(self.name "可以避开障碍物")
#第二代机器人
继承的类是否要用到初始化函数?请看是否从父类里面继承了。
1:父类有的,继承后,我都可以直接拿过来用。
2:父类有,子类也有重名的函数,那么子类的实例就优先调用子类的函数。
# r2=RobotTwo("1990","小王")
#r2.robo_info()
#r2.walking_on_ground()
# r2.walking_avoid_block()
# r1=RobotOne("1988","小明")
# r1.walking_on_ground()#父类只能调用自己的方法
知识点:多继承就是继承多个父类。
#第三代机器人
class RobotThree(RobotTwo,RobotOne):#第三代机器人继承于第一代和第二代机器人的类
#第一代机器人和第二代机器人之间不能有继承关系,不然就会报错,提示重复继承了
def _init_(self,year,name):
self.year=year
self.name=name
def jump(self):
print(self.name "单膝跳跃")
r3=RobotThree("2001","大王")
r3.jump()
r3.walking_on_ground()
r3.walking_avoid_block()
r3.robo_info()
疑问:没有year
参数,调用robot_year
就会报错,怎么办?
没办法解决,自己写函数时注意,避免遇到这种情况。或者重写第三个机器人。
多继承的子类具有两个父类的属性和方法 如果两个父类具有同名方法的时候, 子类调用函数就近原则,初始化函数也包括在内。
封装是什么?
把属性和函数封装到一个类里面就是封装。Python
和Java
中叫法是不一样的。
1.复习点:
1.如果类里面有初始化函数,创建实例的时候,就必须要在实例里面传递对应个数的参数。
2.调用函数的时候,必须实例调用,多复习类函数,静态函数,实例函数。
2.拓展点:
实例存到变量里面去调用方法,还是直接创建实例调用方法?
例如:
方法 1:
User('helen','can','30',165','110').describe_user()
方法 2:
u1=User('helen','can','30',165','110')
u1.describe_user()
创建多个实例会造成内存的浪费,不知道什么时候回收。如果不需要调用别的方法,就用第一种。
如果这个实例在别的地方也需要用到,建议把实例创建后存到一个变量里面,方便随时使用。两种方法实现的效果一样。
3.补充:
grade={"**语文":118,"数学":88,"英语"**:122}
可使用高阶函数 sorted