1、什么是类
- 人类、车类、鸟类、猴类、生物类
- 是一群具有相同 特征 或者 相同行为的事物的一个统称,是抽象的
- Python中的类可以类比为图纸(模子)
- 类只有一个
- 特征:一般是名词,特性, Python中称为属性
- 行为: 一般为动作,Python中称为方法(类似于函数)
2、什么是对象
- 人类:男人 女人 性别不详的人
- 鸟类:麻雀 孔雀 凤凰 鸵鸟
- 对象是一个具体的存在:凤凰
- 对象是由类创建的,并且具有类的特征和行为
- 对象有很多个,可以使用类来创建多个对象
- 每个对象之间,拥有不同的属性值
- 每个对象的实例属性是独有的
2.1对象的概念
某种数据类型的一个具体的数据,个体,对象,就称之为这个类的一个实例或者对象。
比如:1就是整数的一个实例/对象
通过类创建对象叫实例化。
所谓的面向对象,就是把一些数据抽象成类的思想。
3.定义类class
# 类名为大驼峰 class PeopleInfo: """ 定义人类 """ # 类中称为方法 # 类似于函数 def __init__(self, name, age, sex): # 构造方法, 构造器 pass
4.
- 在类中创建的方法,如果带 self, 那么往往把它叫做实例方法
- 创建对象,是一个实例化的过程
- 使用 对象.方法名 来调用方法
- 对象将自身, 自动传给了self, 所以不会报错, 在类里面, self 相当于one_person
- 在类的外面创建属性, ---不推荐使用
- 使用 对象.属性 = 属性值 类似于给变量赋值
- 在类的外面如何调用属性
- 使用 对象.属性 类似于获取变量
class PersonInfo: # 类相当于图纸(模板) """ 定义人类 """ def run(self): # self跟调用方法时的对象ID一致 print("人会跑步") def eat(self): # 在类中创建的方法, 如果带self, 那么往往把它叫做实例方式 print("人会吃饭") one_person = PersonInfo() # 创建对象(盖房子), 是一个实例化的过程 print(f"one_person的ID为: {id(one_person)}") one_person.run() # 使用 对象.方法名 来调用方法 one_person.eat() # 对象将自身, 自动传给了self, 所以不会报错, 在类里面, self相当于one_person # 在类的外面创建属性, ---不推荐使用 # 使用 对象.属性 = 属性值 类似于给变量赋值 one_person.name = "胡巴" one_person.age = 25 one_person.height = 190 # 在类的外面如何调用属性 # 使用 对象.属性 类似于获取变量 print(one_person.name) print(one_person.age) print(one_person.height)
类属性:
- 共有的特征, 那么叫做类属性
- 在类的外面定义的是变量,但是在类名的下面。定义的变量,称为类属性,所以对象共有的特征
类的初始化函数__init__:
- 固定形式, 绝大多数情况下, 会使用__init__方法来创建属性,称为构造方法或者构造器, 推荐做法
- 形参,由类名("雨欣") 来传参实参
- 在构造方法下创建属性,写死:self.fair = "假发"
- 一般在类的里面, 会使用 self.属性 来创建属性:self.name = name
__str__:魔术方法
- 如果使用print函数打印一个对象, 那么会自动调用__str__实例方法
- _str__实例方法,需要返回一个字符串,否则会报错
- 使用return来定义
-
def __str__(self): # 魔术方法 return "<{}>".format(self.name)
在类中创建的方法,如果带 self, 那么往往把它叫做实例方法
可以使用类来创建多个对象,每个对象之间,拥有不同的属性值,每个对象的实例属性是独有的
class PersonInfo: # 类相当于图纸(模板) """ 定义人类 """ # 共有的特征, 那么叫做类属性 head = 1 # 在类的外面定义的是变量, 但是在类名的下面, 定义的变量, 称为类属性, 所以对象共有的特征 def __init__(self, name, age, height): """ 固定形式, 绝大多数情况下, 会使用__init__方法来创建属性,称为构造方法或者构造器, 推荐做法 :param name:形参,由类名("雨欣") 来传参实参 :param age:形参,由类名(16) 来传参实参 :param height:形参,由类名(170) 来传参实参 """ self.fair = "假发" # 创建属性,写死 self.name = name # 一般在类的里面, 会使用 self.属性 来创建属性 self.age = age self.height = height print(f"self的ID为: {id(self)}") # 在类的里面使用self.属性名, 能获取属性的值 print("姓名: {}\n年龄: {}\n身高: {}".format(self.name, self.age, self.height)) def run(self): # self跟调用方法时的对象ID一致,实例方法中,使用self.属性名 来调用 # self.face = "瓜子" # 实例方法中创建属性--不推荐 print("{}会跑步".format(self.name)) def eat(self): # 在类中创建的方法, 如果带self, 那么往往把它叫做实例方法 print("{}会吃饭".format(self.name)) def info(self): # 在类的里面, 可以使用类名.类属性 来获取类属性的值 # print("姓名: {}\n年龄: {}\n身高: {}\n脑袋个数: {}".format(self.name, self.age, self.height, PersonInfo.head)) # 在类的里面, 可以使用self.类属性 来获取类属性的值 print("姓名: {}\n年龄: {}\n身高: {}\n脑袋个数: {}".format(self.name, self.age, self.height, self.head)) def __str__(self): # 魔术方法 # 如果使用print函数打印一个对象, 那么会自动调用__str__实例方法 # 往往__str__实例方法, 需要返回一个字符串 return "<{}>".format(self.name) # 可以使用类来创建多个对象 # 每个对象之间, 拥有不同的属性值 # 每个对象的实例属性是独有的 one_person = PersonInfo("雨欣", 16, 180) # 类名() 默认会调用__init__方法,实参 two_person = PersonInfo("Sunny", 18, 185) # one_person.run() # two_person.run() # two_person.eat() print(one_person) print(two_person) # 在类的外面如何访问类属性? # 1. 类名.类属性 print(PersonInfo.head) # 2. 对象.类属性 print(one_person.head) print(two_person.head) # PersonInfo.info() # 不能使用类名来调用实例方法 # PersonInfo.name # 不能使用类名来调用实例属性 one_person.info() # 可以使用对象名来调用实例方法
5.类方法和静态方法
类方法
格式:
@classmethod # (译:可拉斯.蛮色的)装饰器,类方法来处理类属性的 def angray(cls): # 如果不加装饰器,默认创建实例方法 cls.head = 2 pass
- 使用@classmethod来定义(译:卡拉斯.蛮色的)
- 在类方法里面 调用 或 修改 类属性 -------cls.类属性
- 在类中创建的方法, 如果带self, 那么它叫做实例方法
- 在类的外面可以调用静态方法
- 对象.静态方法
- 类.静态方法
- 在外面,来调实例属性
- 对象.实例属性
- 在外面,调用类属性
- 对象.类属性
- 在外面,调用类方法
- 对象.类方法
- 当对象调用类方法时, 会把对象所属的类ID自动赋值给cls
- 在类的外面修改类属性--不推荐
- 类名.类属性
- 对象不能调用类外面的函数
- 对象.函数名
静态方法
格式:
@staticmethod # (译:四大题刻.蛮色的 )定义的是静态方法, 静态跟类外面定义的函数几乎没有区别, 只不过是位置不同以 def weather_forecase(motion): """ 播报天气 在类的外面定义的一定是函数, 在类的里面定义的才是方法 :return: """ print("天气, 晴朗!") print("温度: 22°") print("适合出游")
- 使用@staticmethod来定义
- 在类的外面调用静态方法
- 对象.静态方法
- 类.静态方法
- 在类的里面调用静态方法
- self.静态方法
- 在类里面的类方法内调用静态方法
- cls.静态方法
- 在类的里面可以调用类外面的函数
问题:
1、实例方法和类方法、静态方法有什么区别?
1、第一个参数:实例方法是 self,类方法是 cls,静态方法没有必传参数。
2、类方法用 @classmethod 装饰。静态方法用 @staticmethod 装饰。
3、实例方法,一定要有对象能访问。
类方法,不需要对象直接类名访问,类和对象都可以访问。
静态方法,对象和类都可以访问。
函数与方法:
类当中定义的函数,叫做方法
不在类当中定义的函数。
一定要有实例化对象才能访问的。
实例属性:
定义的时候:self.属性名 = 值
调用的时候:对象名.属性名
实例方法:
定义的时候:方法的第一参数是self
调用的时候:对象名.方法名(有参传参)
在实例方法当中,可不可以通过self调用其它的实例方法???
可以
注意:方法不要互相调用
知识点:
实例属性,都在__init__方法中定义初始值。
实例方法,第一个参数必须是self。在实例方法当中,可以修改实例属性的值。
6.类的内部和外部调用
代码案例:
class NumDeal: num_type = '数字类型' num_amount1 = 11 num_amount2 = 33 def __init__(self, num1, num2): self.num1 = num1 self.num2 = num2 print(f'类内部调用类方法nums_sum:{self.nums_sum()}') # 类内部调用类方法,因为创建了两次实例对象,所以调用该方法时传入两个对象的实例变量值 print(f'类内部调用实例方法nums_add:{self.nums_add()}') # 类内部调用类方法,因为创建了两次实例对象,所以调用该方法时传入两个对象的实例变量值 print(f'类的内部调用实例属性num1:{self.num1},num2:{self.num2}') # 因为创建了两个实例化对象,所以会调用初始化函数两次,分别打印出两个对象分别传入的值 print(f'类的内部调用类属性num_type:{self.num_type},num_amount1:{self.num_amount1},num_amount2:{self.num_amount2}') def nums_add(self): # 实例方法 return self.num1 + self.num2 @classmethod # 定义类方法需要用装饰器@classmethod def nums_sum(cls): # 类方法 return cls.num_amount1 + cls.num_amount2 num_int = NumDeal(4, 5) num_float = NumDeal(4.1, 5.1) print('*'*30, 'num_int', '*'*30) print(f'类外边通过类实例对象num_int调用类属性:{num_int.num_type}') print(f'类外边通过类实例对象num_int调用实例属性num1:{num_int.num1},num2:{num_int.num2}') print(f'类外边通过类实例对象num_int调用实例方法nums_add(两个int类型数字相加结果):{num_int.nums_add()}') print(f'类外边通过类实例对象num_int调用类方法nums_sum():{num_int.nums_sum()}') print() print('*'*30, 'num_float', '*'*30) print(f'类外边通过类实例对象num_float调用类属性:{num_float.num_type}') print(f'类外边通过类实例对象num_float调用实例属性num1:{num_float.num1},num2:{num_float.num2}') print(f'类外边通过类实例对象num_float调用实例方法nums_add(两个float类型数字相加结果):{num_float.nums_add()}') print(f'类外边通过类实例对象num_float调用类方法nums_sum():{num_float.nums_sum()}') print() print('*'*30, 'NumDeal', '*'*30) print(f'类外边通过类名NumDeal调用类属性:{NumDeal.num_type}') # print(f'类外边通过类名NumDeal调用实例属性num1:{NumDeal.num1}') # 会报错,说明不能用类名调用实例属性 # print(f'类外边通过类名NumDeal调用实例方法nums_add():{NumDeal.add()}')#会报错,说明不能用类名调用实例方法 # print(f'类外边通过类名NumDeal调用实例方法nums_add(:{NumDeal.nums_add(num_int)}') # 可以在调用实例方法是传入类实例对象 print(f'类外边通过类名NumDeal调用类方法nums_sum():{NumDeal.nums_sum()}')
执行结果:
类内部调用类方法nums_sum:44 类内部调用实例方法nums_add:9 类的内部调用实例属性num1:4,num2:5 类的内部调用类属性num_type:数字类型,num_amount1:11,num_amount2:33 类内部调用类方法nums_sum:44 类内部调用实例方法nums_add:9.2 类的内部调用实例属性num1:4.1,num2:5.1 类的内部调用类属性num_type:数字类型,num_amount1:11,num_amount2:33 ****************************** num_int ****************************** 类外边通过类实例对象num_int调用类属性:数字类型 类外边通过类实例对象num_int调用实例属性num1:4,num2:5 类外边通过类实例对象num_int调用实例方法nums_add(两个int类型数字相加结果):9 类外边通过类实例对象num_int调用类方法nums_sum():44 ****************************** num_float ****************************** 类外边通过类实例对象num_float调用类属性:数字类型 类外边通过类实例对象num_float调用实例属性num1:4.1,num2:5.1 类外边通过类实例对象num_float调用实例方法nums_add(两个float类型数字相加结果):9.2 类外边通过类实例对象num_float调用类方法nums_sum():44 ****************************** NumDeal ****************************** 类外边通过类名NumDeal调用类属性:数字类型 类外边通过类名NumDeal调用类方法nums_sum():44
1、实例属性
在类的外面
-
- 赋值(创建)
- 对象.属性名-------不推荐
- 类.实例属性名 = 属性值
- 错误用法,执行报错
- 调用
- 对象.属性名
- 类.实例属性名 = 属性值
- 错误用法,执行报错
- 赋值(创建)
在类的里面
-
- 赋值(创建)
- 使用__init__方法来给实例实例属性赋值
- self.属性名 = 属性值
- cls.实例属性名 = 属性值
- 错误用法,执行报错
- 调用
- self.属性名
- cls.实例属性名
- 错误用法,执行报错
- 赋值(创建)
2、类属性
在类的外面
-
- 赋值(创建)
- 类名.类属性名 = 类属性值
- 对象.类属性名 = 类属性值
- 错误用法,执行报错
- 调用
- 类名.类属性名
- 对象.类属性名
- 赋值(创建)
在类的里面
-
- 赋值(创建)
- 类名.类属性名 = 类属性值
- cls.类属性名 = 类属性值
- self.类属性名 = 类属性值
- 错误用法,执行报错
- 调用
- 类名.类属性名
- cls.类属性名
- self.类属性名
- 赋值(创建)
3、实例方法
在类的外面
-
- 调用
- 对象.实例方法()
- 类名.实例方法()
- 错误用法,执行报错
- 调用
在类的里面
-
- 赋值(创建)
- 类名.类属性名 = 类属性值
- cls.类属性名 = 类属性值
- self.类属性名 = 类属性值
- 错误用法,执行报错
- 调用
- self.实例方法()
- 类名.实例方法()
- 错误用法,执行报错
- cls.实例方法()
- 错误用法,执行报错
- 赋值(创建)
4、类方法
在类的外面
-
- 调用
- 类名.类方法()
- 对象.类方法()
- 调用
在类的里面
-
- 调用
- 类名.类方法()
- self.类方法()
- 调用
5、静态方法
在类的外面
-
- 调用
- 类名.静态方法(参数)
- 对象.静态方法(参数)
- 调用
在类的里面
-
- 调用
- 类名.静态方法(参数)
- self.静态方法(参数)
- cls.静态方法(参数)
- 调用
7.类的继承、重写、拓展、超继承
继承:
- 子类可以直接调用继承的父类中的属性值:self/name
- 使用类名(父类名) 来继承父类的所有方法, 私有方法和私用属性除外(__one_methond)
- 被继承也可以叫做:父类、超类、基类
- 继承父类的类叫做:子类
私有属性/方法
1、不想被子类继承
2、不想被外部访问
3、私有属性/方法,仅在类内部。
私有化的属性/方法:仅给类内部使用。
私有化的方式:
1、_属性/方法: 子类/对象都可以访问_属性/方法,但是,不希望被访问。
2、__属性/方法: 子类/对象不可以访问__属性/方法。 双下划綫级别会更高
class Parent: def __init__(self, id): print("我是爸爸,我有财产。我的id是{}".format(id)) self._flag = "涨薪3000" # 定义私有化属性 self.__flag = "涨薪3000" def run(self): print("爸爸会跑!!!") # 类内部访问私有属性 def print_flage(self): print(self.__flag) # 继承 - 拥有父类的所有方法 class Son(Parent): def print_money(self): print(self._flag) # 可以打印出来,但是 . 的时候没有联想 print(self.__flag) # 子类/对象不可以访问__属性/方法。 s = Son(1111111) s.run() # print(s._flag) # 可以打印出来,但是 . 的时候没有联想 # print(s.__flag) # 会报错,提示没有这个属性 s.print_money() # 会报错,子类/对象不可以访问__属性/方法。
重写:super().父类方法
- 对父类方法的重写,如果定义了跟父类一样的方法名,那么会将父类同名的方法覆盖掉
- 重写后,子类调用的是重写后的实例方法
- super().父类方法,能够调用父类的方法,是Python3中的方法,重写
继承之后,对于父类已有的方法,进行重写 (改进父类的同名方法、全面颠覆父类的同名方法)。
在子类当中,调用父类的同名方法:super
super().父类的同名方法(有参传参)
因为如果使用 self 去调,就会直接调用子类的同名方法。
就近原则:子类有的方法,直接使用子类。子类没有的方法,才去父类找。
class Parent: def __init__(self, id): print("我是爸爸,我有财产。我的id是{}".format(id)) def run(self): print("爸爸会跑!!!") def sleep(self, place): print("在 {} 休息".format(place)) # 继承之后,要对父类的同名方法,进行优化。。 class Son(Parent): # 通常会去调用父类的初始化方法,并额外增加子类想要做的初始化代码。 # 父类的__init__参数必须有,可以额外再添加其它参数。 def __init__(self, my_id): super().__init__(my_id) # 调用 父类的方法 print("我是儿砸,我是女儿!!") # self.run() # 如果与父类不重名,一般都是通过self去调用 # super().run() def sleep(self, my_place, pet_name): super().sleep(my_place) # super 调用 父类的方法 print("和{}一起!!".format(pet_name)) s = Son(1234567890) # s.run() s.sleep("公司", "老板家的狗子") # 继承之后,不对父类作任何改动,仅仅在父类的基础上,增加了其它的方法 class Son2(Parent): def eat(self): print("会吃!!!") def cooking(self): print("做饭666666") def sport(self): print("开始运动!") self.run()
多重继承:了解
class Grand: def run(self): print("爷爷会跑!!!") class Parent(Grand): def __init__(self,id): print("我是爸爸,我有财产。我的id是{}".format(id)) def run(self): print("爸爸会跑!!!") def sleep(self,place): print("在 {} 休息".format(place)) # 继承之后,要对父类的同名方法,进行优化。。 class Son(Parent): # 通常会去调用父类的初始化方法,并额外增加子类想要做的初始化代码。 # 父类的__init__参数必须有,可以额外再添加其它参数。 def __init__(self,my_id): super().__init__(my_id) print("我是儿砸,我是女儿!!") # self.run() # 如果与父类不重名,一般都是通过self去调用 # super().run() def sleep(self,my_place, pet_name): super().sleep(my_place) print("和{}一起!!".format(pet_name)) def run(self): super().run() # 就近原则 Son(1111111).run()
多继承
class Student: def study(self): print("学习,投资自己") class Employee: def own_money(self): print("赚钱") class People(Student, Employee): def run(self): print("会跑") People().study()
拓展:
拓展,,在父类的方法的基础上,新增内容;super().__init__ 代表父类,代表创建了对象调用了 init方法
超继承:
def info(self): # 定义与父类同样的方法 # super()能够调用父类的方法, 是Python3中的方法 super().info() # 调用父类的方法 print("工作: {}".format(self.job)) # 在本子类中添加新的内容,即继承了父类中的方法,也添加了新的内容
示例:
class Animal(object): # 如果一个类, 没有显示继承一个类, 那么默认会继承object(祖宗类) """ 定义动物类 :object 写与不写都一样,如果一个类, 没有显示继承一个类, 那么默认会继承object(祖宗类) """ def __init__(self, name, age, color): self.name = name self.age = age self.color = color def eat(self): print("{}需要吃东西".format(self.name)) def drink(self): print("{}需要喝水".format(self.name)) def run(self): print("{}会跑步".format(self.name)) def sleep(self): print("{}需要睡觉".format(self.name)) def info(self): print("姓名: {}\n年龄: {}\n颜色: {}".format(self.name, self.age, self.color)) class Dog(Animal): """ 使用类名(父类名) 来继承父类的所有方法, 私有方法和私用属性除外(__one_methond) 被继承的类也可以叫做:父类、超类、基类;继承父类的类叫做子类 """ def bark(self): print("{}会汪汪叫".format(self.name)) class XiaoTianQuan(Dog): def __init__(self, name, age, color, job): # 拓展, 在父类的方法的基础上, 新增内容;super().__init__ 代表父类,代表创建了对象调用了 init方法 self.name = name self.age = age self.color = color super().__init__(name, age, color) self.job = job def fly(self): print("{}会飞".format(self.name)) def sleep(self): # 对父类方法的重写,如果定义了跟父类一样的方法名, 那么会将父类同名的方法覆盖掉 print("{}是神仙, 不需要睡觉".format(self.name)) def info(self): # Python2中, 可以使用super(子类名, self).父类的方法 super(XiaoTianQuan, self).info() # super().父类方法,能够调用父类的方法, 是Python3中的方法,重写 super().info() print("工作: {}".format(self.job)) class Cat(Animal): def catch(self): print("{}会抓老鼠".format(self.name)) if __name__ == '__main__': taidi = Dog("泰迪", 1, '黑色') taidi.weight = 2 # 动态创建属性, 比较少见, 也有应用场景 xiaotianquan = XiaoTianQuan("哮天犬", 1000, "金色") xiaotianquan = XiaoTianQuan("哮天犬", 1000, "金色", "守护天庭") taidi.info() xiaotianquan.sleep() # 重写方法:将父类的方法覆盖掉 xiaotianquan.info()
多态:了解
python没有多态,python处处皆多态 -- python的函数,参数不需要申明类型,也不会限定类型。
python: 鸭子类型
Java语言:函数的任意参数,必须申明是什么类型。传参一定要是指定的数据类型,否则就报错。
多态:父类类型,接收子类对象。
# 父类 class People: def run(self): print("人会跑") # 子类 class Student(People): def run(self): print("学生会跑") # 子类 class Employee(People): def run(self): print("员工会跑") class Dunk: def run(self): print("鸭子会跑") # python当中函数的参数 def can_run(obj): obj.run() e1 = Employee() # 判断e1是不是Employee类的对象, e1是不是Employee父类People的对象?? print(isinstance(e1, Employee)) # True print(isinstance(e1, People)) # True # e1 = Employee() # # 对象作为函数的参数 # can_run(e1) # # can_run("hello world") # s1 = Student() # # 对象作为函数的参数 # can_run(s1) # # p1 = People() # # 对象作为函数的参数 # can_run(p1) # # d1 = Dunk() # # 对象作为函数的参数 # can_run(d1)
重载:了解
java语言:
1、函数的参数,必须指定数据类型
2、函数的参数,没有不定长类型。
解决:
1、同一函数名,参数支持不同的数据类型。
--- python而言,参数类型不受限制。
2、同一函数名,支持参数个数不一样。
--- python而言,*args, **kwargs
# 别的语言java: 参数是个整数 def hello_world(int a): print("11111") # 别的语言java: 参数是个符点数 def hello_world(float b): print("222222") # 别的语言java: 参数是个符点数 def hello_world(float b, float c): print("333333")
反射:了解
hasattr(对象/类,属性名) -- 对象/类是否有属性,如果有为True,如果没有为False
setattr(对象/类,属性名,属性值) -- 给对象/类是 添加/修改属性值.如果属性存在,则是修改.如果属性不存在,则是添加.
getattr(对象/类,属性名) -- 获取对象/类的属性值
delattr(对象/类,属性名) -- 删除对象/类的属性和属性值
class People: def run(self): print("人会跑") p = People() p.hello = "11111" # 添加属性 print(p.hello) if hasattr(p, "hello"): # 对象/类是否有属性 print("已存在") else: setattr(p, "hello", "66666") # 给对象/类是 添加/修改属性值 print(getattr(p, "hello")) # 获取对象/类的属性值 # print(p.hello) delattr(p, "hello") # 删除对象/类的属性和属性值 # print(getattr(p, "hello")) # 在获取 会报错:AttributeError: 'People' object has no attribute 'hello' if hasattr(People, "kind"): print("已存在") else: setattr(People, "kind", "人类") print(getattr(People, "kind")) # 类访问kind属性 print(getattr(p, "kind")) # 对象访问kind属性 delattr(People, "kind")
练习题:
1.什么是类?什么是对象?
什么是类?
-
- 类 是对一群具有 相同特征 或者 行为 的事物的一个统称
- 抽象的
什么是对象?
-
- 对象 是 由类创建出来的一个具体存在
- 具体的
2.类由哪几部分构成?
- 特征 被称为 属性
- 它是什么样的
- 行为 被称为 方法
- 它可以做什么
3.列举几个生活中类和对象的例子
- 建筑物图纸为类,建造出来的房子为对象
- 狗为类,泰迪为对象
- 测试为类,测试用例为对象
4.类的设计原则
请从类的命名、类中属性和方法来阐述
- 类名
- 满足大驼峰命名法
- 分析 整个业务流程,找出其中的 名词
- 属性
- 这类事物具有什么样的特征
- 找名词
- 方法
- 这类事物具有什么样的行为
- 找动词
5.实例方法的特性?__init__方法的作用?
类中实例方法的特性?
-
- 第一个参数一定为self
- 只能被对象调用
- 对象.实例方法,会将对象自身传给self
__init__方法的作用?
-
- 创建属性并初始化
- 类名(参数) 会调用__init__(self, 参数)方法
6.实例方法与类方法的区别?
实例方法
- 只能被对象调用
- 第一参数为self,在调用时会自动将对象自身传给self
- 作用:处理实例属性
- 在类外
- 对象.实例方法(self, 参数)
- 在类里
- self.实例方法(参数)
类方法
- 能被对象、类来调用
- 需要使用@classmethod装饰器以及第一个参数为cls
- 在类外
- 对象.类方法(cls, 参数) 会将对象的类传给cls
- 类.类方法(cls, 参数) 会将类传给cls
- 在类里
- self.类方法(cls, 参数) 会将对象的类传给cls
- 类.类方法(cls, 参数) 会将类传给cls
- 作用:
- 处理类属性
7.在类的里面和类的外面,调用实例方法、实例属性、类属性的方式?
- 参考第6题,或上面总结的6.类的内外部调用
8.__str__实例方法的作用?
- 打印对象时会调用
- 必须return 字符串
9.编写如下程序,灰色的Tom猫,今年1岁,吃着美味的食物,喝着可口的饮料,非常享受的样子
- a.根据以上信息,抽象出一个类
- b.定义相关属性,并能在类的外面调用
- c.定义相关方法,在方法中打印相应信息
class Cat: """ create a cat class """ def __init__(self, name, color, age): """ 构造方法 :param name: 姓名 :param color: 颜色 :param age: 年龄 """ self.name = name self.color = color self.age = age self.status = [] # 状态 def eat(self): print("{}正在吃东西...".format(self.name)) self.status.append("舔嘴巴") def drink(self): print("{}正在喝饮料...".format(self.name)) self.status.append("喵喵喵...") tom = Cat("Tom", "灰色", 1) print("名字:{}\n颜色:{}\n年龄:{}".format(tom.name, tom.color, tom.age)) tom.eat() tom.drink() print("{}很享受的样子,{}、{}".format(tom.name, *tom.status))
10.类方法、静态方法分别是什么?有作用?如何定义?
类方法是什么?
- 针对 类 定义的方法
作用?
- 处理类属性
如何定义?
@classmethod def 类方法名(cls): pass
- 需要修饰器 @classmethod 来标识
- 第一个参数一般为 cls
- 在类方法内部,可以直接使用 cls 访问 类属性 或者 调用类方法
静态方法是什么? 作用?
- 与对象和类没有直接关系的一段逻辑
- 但在类中要调用某一个函数,为了类的封装性,往往会将类外面定义的函数拿到类里面来定义
如何定义?
@staticmethod def 静态方法名(参数): pass
- 需要修饰器 @staticmethod 来标识
- 在类里面和类外面,都能被对象和类来调用
11.类方法、静态方法分别如何调用?
答案参考题1
12.什么是继承?有什么特性?
什么是继承?
- 获取已存在类的资源(方法和属性)
有什么特性?
- 能够继承父类的所有方法,私有方法除外
13.编写如下程序,创建一个名为 Restaurant类,要求至少拥有饭店名和美食种类这两个特征。
- a.需要创建一个方法来描述饭店名和美食种类相关信息
- b.同时能够显示饭店营业状态(例如:正在营业)
class Restaurant: def __init__(self, name, *args): self.name = name self.args = args def description(self, status): if status == 'OPEN': print('{}饭店营业正常营业'.format(self.name)) for item in self.args: print('美食种类有:{}'.format(item)) elif status == 'CLOSED': print('{}饭店暂停营业,欢迎下次光临!'.format(self.name)) if __name__ == '__main__': a = Restaurant('金手勺', '米饭', '馒头', '大饼') a.description('OPEN') a.description('CLOSED')
方式二:
class Restaurant: """ 创建一个餐馆类 """ def __init__(self, restaurant_name, cooking_type): self.restaurant_name, self.cooking_type = restaurant_name, cooking_type def describe_restaurant(self): print("*" * 46) print("{:^40s}\n".format(self.restaurant_name)) for key, item in enumerate(self.cooking_type, start=1): print("\t{}.{}".format(key, item)) print("\t请点餐,祝您用餐愉快!") print("*" * 46) def open_restaurant(self): print("{},正在营业...".format(self.restaurant_name)) cooking_types = ["北京烤鸭", "四川麻婆豆腐", "西湖醋鱼", "飞龙汤", "无为熏鸭", "东坡肉", "腊味合蒸", "辣子鸡", "东安子鸡", "清 蒸武昌鱼"] famous_restaurant = Restaurant("可优吃不腻餐馆", cooking_types) famous_restaurant.describe_restaurant() famous_restaurant.open_restaurant()
14.编写如下程序,编写一个数学计算类,要求初始化方法带参数(传两个数字),能够实现加减乘除运算。
class MathOperation: """ 数学运算类 """ def __init__(self, one_num, two_num): self.first_num, self.second_num = one_num, two_num def add(self): return self.first_num + self.second_num def minus(self): return self.first_num - self.second_num def multiply(self): return self.first_num * self.second_num def divide(self): try: return round(self.first_num / self.second_num, 2) # 相乘之后四舍五入 except ZeroDivisionError: # print("出现除0错误!") return "∞" if __name__ == '__main__': # one_number = 10 # two_number = 0 # math_operate = MathOperation(one_number, two_number) # print("{} + {} = {}".format(one_number, two_number, math_operate.add())) # print("{} - {} = {}".format(one_number, two_number, math_operate.minus())) # print("{} * {} = {}".format(one_number, two_number, math_operate.multiply())) # print("{} / {} = {}".format(one_number, two_number, math_operate.divide())) nums = (10, 0) # 传入两个参数 math_operate1 = MathOperation(*nums) # *号代表解包:10和0 print("{} + {} = {}".format(*nums, math_operate1.add())) print("{} - {} = {}".format(*nums, math_operate1.minus())) print("{} * {} = {}".format(*nums, math_operate1.multiply())) print("{} / {} = {}".format(*nums, math_operate1.divide()))
15.编写如下程序,编写一个工具类和工具箱类,工具需要有的名称、功能描述、价格,工具箱能够添加工具、删除工具、查看工具,并且能获取工具箱中工具的总数。
class Tool: """ 定义工具类 """ def __init__(self, name, desc, price): """ 构造方法 :param name: 工具名称 :param desc: 工具描述 :param price: 工具价格 :return: 无 """ self.name, self.desc, self.price = name, desc, price def describe_tool(self): """ 获取工具描述信息 :return: """ print("\n{:*^100}".format("开始描述")) print(f"名称:{self.name}\n功能:{self.desc}\n价格: {self.price}") print("{:*^100}\n".format("结束描述")) def __str__(self): return "<{}>".format(self.name) class ToolPackage: """ 定义工具箱类 """ tools_count = 0 def __init__(self, name): self.name = name self.all_tools = [] # 存放工具的列表 def add(self, one_tool): """ 添加工具到工具箱中 :param one_tool: Tool工具对象 :return: """ if isinstance(one_tool, Tool): self.all_tools.append(one_tool) self.modify_tool_count() print("成功添加【{}】到【{}】中!".format(one_tool.name, self.name)) else: print("{}不是工具对象,无法添加!".format(one_tool)) def has_tool(self, one_tool): """ 判断工具是否在工具箱中 :param one_tool: Tool工具对象或者工具名 :return: True or False """ if isinstance(one_tool, Tool): # 如果one_tool是工具对象 return one_tool in self.all_tools # 判断是否在工具箱中 elif isinstance(one_tool, str): # 如果是工具名,字符串 for tool_obj in self.all_tools: if one_tool == tool_obj.name: return True return False def remove(self, one_tool): """ 删除工具 :param one_tool: Tool工具对象或者工具名称 :return: """ if self.has_tool(one_tool): # 如果要删除的工具存在 if isinstance(one_tool, Tool): # 如果one_tool为Tool工具对象 self.all_tools.remove(one_tool) else: # 为工具名称字符串 for index, item in enumerate(self.all_tools): if one_tool == item.name: # 当前遍历的工具名为 one_tool self.all_tools.pop(index) break # 删除之后,退出循环 else: print("工具不存在,无法删除!") def search(self, one_tool): """ 根据工具对象或者工具名称查找工具 :param one_tool: Tool工具对象或者工具名称 :return: """ if self.has_tool(one_tool): if isinstance(one_tool, Tool): # 如果one_tool为Tool工具对象 one_tool.describe_tool() else: # 为工具名称字符串 for index, item in enumerate(self.all_tools): if one_tool == item.name: # 当前遍历的工具名为 one_tool self.all_tools[index].describe_tool() break # 找到工具之后,退出循环 else: print("工具不存在!") @classmethod def modify_tool_count(cls): """ 类方法,每调用一次工具总数加一 :return: """ cls.tools_count += 1 @classmethod def get_tool_count(cls): """ 类方法,获取工具箱中,工具总数 :return: """ return cls.tools_count hammer = Tool("锤子", "由金属或木头等材料做成的头和与之垂直的柄构成的敲击工 具。", 25.2) screwdriver = Tool("螺丝刀", "是一种用来拧转螺丝以使其就位的工具,通常有一个薄 楔形头,可插入螺丝钉头的槽缝或凹口内。", 5) saw = Tool("锯子", "用来把木料或者其他需要加工的物品锯断或锯割开的工具。", 12) electric_drill = Tool("电钻", "利用电做动力的钻孔机具。", 278) family_tool_package = ToolPackage("家用工具箱") # 将工具添加到工具箱中 family_tool_package.add(hammer) family_tool_package.add(screwdriver) # 删除一个不存在的工具 family_tool_package.remove(saw) # 按照工具的名字来删除一个工具 family_tool_package.remove("锤子") # 再次添加工具 family_tool_package.add(electric_drill) # 查询工具 family_tool_package.search(saw) # 查询不存在的工具 family_tool_package.search(screwdriver) # 查询已存在的工具 family_tool_package.search("电钻") # 通过工具名来查询工具 # 获取工具总数 print("{}中现在有【{}】件工具。".format(family_tool_package.name, family_tool_package.get_tool_count()))
*******请大家尊重原创,如要转载,请注明出处:转载自:https://www.cnblogs.com/shouhu/,谢谢!!*******