Python学习笔记(8)-类

小灰灰 2022-07-14 13:25 249阅读 0赞

创建和简单使用

类可以反映现实的事物。

代码:

  1. class Dog(): # 类名首字母大写
  2. """模拟小狗的简单测试"""
  3. def __init__(self, name, age): # 该方法在类创建的时候会自动运行,类似java的构造函数,注意方法名开头和末尾各有两个下划线
  4. """初始化属性name和age"""
  5. self.name = name
  6. self.age = age
  7. def sit(self): # 每个与类相关联的方法,都会传入参数self
  8. """模拟坐的动作"""
  9. print(self.name.title() + " 坐下") # 可获取初始化方法中的值,因传递了参数self
  10. def roll(self, count): # 可根据需求自定义要传入的参数,但是self是固定的
  11. """模拟打滚的动作"""
  12. print(self.name.title() + " 滚了 " + str(count) + " 圈")
  13. my_dog = Dog('二哈', 3) # 此处要传入类的初始化方法里的参数
  14. print("我的小狗名字是:" + my_dog.name + "\n年龄是:" + str(my_dog.age))
  15. my_dog.sit()
  16. my_dog.roll(4) #传入自定义的count参数

结果:

  1. 我的小狗名字是:二哈
  2. 年龄是:3
  3. 二哈 坐下
  4. 二哈 滚了 4

使用类和实例

先创建一个Car类

  1. class Car():
  2. """模拟汽车"""
  3. def __init__(self, make, model, year=2016): # 默认时间为2016,如果指定参数了,则按照传入的参数处理,同上一章内容
  4. """初始化汽车数据"""
  5. self.make = make
  6. self.model = model
  7. self.year = year
  8. def describe(self):
  9. """返回描述信息"""
  10. message = "车类别:" + self.make + " 车型号:" + self.model + " 制造时间:" + str(self.year)
  11. return message # 也可以直接打印
  12. my_car_1 = Car('奥迪', 'R8', 2015) # 指定时间参数是2015
  13. my_car_2 = Car('宝马', 'Z7') # 再创建一个实例,没有指定时间参数
  14. print(my_car_1.describe())
  15. print(my_car_2.describe())

结果:

  1. 车类别:奥迪 车型号:R8 制造时间:2015
  2. 车类别:宝马 车型号:Z7 制造时间:2016

修改已创建实例的属性值

(注意:修改后改变的仅是该实例的属性值,而其他同一个类创建的实例属性值不受影响)

代码:

  1. class Car():
  2. # --snip--
  3. # 修改属性的值,直接访问修改,也可将该逻辑写在类创建的一个函数中,直接调用修改
  4. my_car_1.year = 2000 # 制造时间改为2000年
  5. print(my_car_1.describe())
  6. my_car_1.color = 'red' # 增加属性的值,直接赋值给新属性即可,同字典
  7. print(my_car_1.color)
  8. print(my_car_2.color) # 此句报错,因为car2并没有color属性

结果:

  1. 车类别:奥迪 车型号:R8 制造时间:2000
  2. red
  3. AttributeError: Car instance has no attribute 'color'

类的访问限制

java中访问控制符有public,private等,python中属性也有控制符,如下的类中。

代码:

  1. class Person():
  2. def __init__(self, name, age):
  3. self.__name = name # 由两个下划线开始的属性表示类的私有属性,外部无法正常访问
  4. self.__age = age
  5. def say(self): # 私有属性只能自己内部访问
  6. print ('name:' + self.__name + 'age:' + str(self.__age))
  7. p1 = Person('吴彦祖 ', 18)
  8. p1.say()
  9. print (p1.__name) # 此句报错,同理,无法修改相应属性

结果:

  1. name:吴彦祖 age:18
  2. AttributeError: Person instance has no attribute '__name'

同java,外部要想访问或修改,可在类内部创建set()get()方法 ,如下

代码:(类中新增添set和get方法)

  1. class Person():
  2. # --snip--
  3. def set_name(self, name): # 可在方法中控制,避免修改成无效的数据
  4. self.__name = name
  5. def get_name(self):
  6. return self.__name
  7. p1 = Person('吴彦祖', 18) # 获取实例
  8. print (p1.get_name()) # 访问属性
  9. p1.set_name('刘德华') # 修改属性
  10. print (p1.get_name()) # 访问属性

结果:

  1. 吴彦祖
  2. 刘德华

Tip:有时会遇到单下划线开头的变量,如_name,意思是建议当做私有变量,但外部还是可以访问的(我不知道为毛这样设计,先暂时这么记吧,以后知道了再做修改)

双下划线开头的私有变量,外部其实也是可以访问的,例如

  1. p1._Person__name

是因为python类内部封装了__name属性,但不建议这么写,因为不同版本的Python解释器可能会把__name改成不同的变量名

最后要注意的是:添加修改属性时,不能添加修改私有属性。例如

  1. p1 = Person('吴彦祖', 18)
  2. p1.__name = '刘德华' # 本意修改name的值
  3. print (p1.get_name()) # 实际上并未修改
  4. print (p1.__name) # 只是新增添了__name属性

结果:

  1. 吴彦祖
  2. 刘德华

但可以通过p1._Person__name方法修改,但不建议,理由同上

继承

1.子类创建时候,初始化方法里需要调用父类的__init__()方法,获得父类的所有属性和方法,还可定义自己独有的属性和方法,重写父类的方法等
代码:

  1. class ElectricCar(Car): # 继承父类时,将父类写入括号内即可
  2. """电动车"""
  3. def __init__(self, make, model, year):
  4. """初始化父类的属性"""
  5. super().__init__(make, model, year) # 注意super的括号,→_→
  6. # 初始化自己独有的属性
  7. self.battery = 70
  8. # 定义独有的方法
  9. def describe_battery(self):
  10. print("电池容量:" + str(self.battery))
  11. my_tesla = ElectricCar('特斯拉', 'S', 2011)
  12. print(my_tesla.describe())
  13. my_tesla.describe_battery()

结果:

  1. 车类别:特斯拉 车型号:S 制造时间:2011
  2. 电池容量:70

2.重写父类的方法,同java类似,实例只执行子类的同名方法

若Car类中有fill_gas方法,但对子类电动车来说无意义,所以子类ElectricCar可以重写父类的fill_gas方法,做出友好的提示。
代码:

  1. class ElectricCar(Car): # 继承父类时,将父类当做参数
  2. # --snip--
  3. # 重写父类的方法,方法名相同
  4. def fill_gase_tank(self):
  5. """电动车没有汽油"""
  6. print("电动车不需要加油,你四不四洒.")
  7. # --snip--
  8. my_tesla.fill_gase_tank()

结果:

  1. 电动车不需要加油,你四不四洒.

3.可以将实例作为某个类的属性

例如新建Battery类

  1. class Battery():
  2. """电池类"""
  3. def __init__(self, battery_size=10): #默认10
  4. self.battery_size = battery_size
  5. def describle(self):
  6. print("电池容量是:" + self.battery_size)

将Battery类作为参数,传递给ElectricCar类,修改ElectricCar类的初始化方法
代码:

  1. def __init__(self, make, model, year):
  2. """初始化父类的属性"""
  3. super().__init__(make, model, year)
  4. # 初始化自己独有的属性
  5. self.battery = Battery() # 此处直接新建Battery的实例赋值给battery属性,没有参数传递,使用默认值10

调用的时候
代码:

  1. my_tesla.battery.describle()

结果:

  1. 电池容量是:10

4.多态和python的鸭子类型

java中的多态,父类定义了一个方法A,子类有重名的方法A,若调用父类其他方法B(调用A)中传入的参数是父类类型,则调用子类相应的重名方法。例如

代码:

  1. class A():
  2. def say(self): # A中有方法say()
  3. print ('A说话了')
  4. def say_twice(self, A): # 调用say方法,但是传入A类型的数据
  5. A.say()
  6. A.say()
  7. class B(A): # B中有方法say()
  8. def say(self):
  9. print ("B说话了")
  10. class C(A): # C中有方法say()
  11. def say(self):
  12. print ("C说话了")
  13. a = A()
  14. b = B()
  15. c = C()
  16. a.say_twice(b) # 调用A的say_twice方法,传入子类b的实例,因为b继承自A,所以调用b的say方法
  17. a.say_twice(c) # 同上

结果:

  1. B说话了
  2. B说话了
  3. C说话了
  4. C说话了

因为java是静态语言,定义好类的方法中传入的数据类型,即必须符号要求的数据类型才能传入,而python是动态语言,只要类中有同名方法(如上代码中的say()),即可传入该类的实例,例如,再定义一个D类,包含say方法

代码:

  1. class D():
  2. def say(self):
  3. print ('D没继承,照样说话了')
  4. d = D()
  5. a.say_twice(d) # 传入D的实例d,虽然没有继承A,但是有say方法,同样可以执行D的say方法,若不包含say方法,则这样调用报错

结果:

  1. D没继承,照样说话了
  2. D没继承,照样说话了

这样的类型就是鸭子类型(长得像鸭子,就是鸭子→_→搞不懂为毛用鸭子)

导入类

同之前的导入函数类似,使用from xxx impoort xxx语句

  1. from car import Car # 第一个car是car.py文件,第二个Car是类,即从某个.py文件中导入某个类
  2. from car import Car, ElectricCar #导入多个类,用逗号分开
  3. import car # 或者直接导入整个模块,同上一章,使用的时候用 car.xxx
  4. from car import * #导入某个模块的所有类和方法,不建议这样用,可能会和当前文件的某些类或者函数名重合导致出错

Python标准库

Python标准库是一组系统自带的模块,包含很多常用的方法
代码:

  1. from collections import OrderedDict # 导入有序字典
  2. users_age = OrderedDict() # 返回一个有序的字典
  3. users_age['大娃'] = 1
  4. users_age['二娃'] = 2
  5. users_age['三娃'] = 3
  6. for name, age in users_age.items():
  7. print("名字是:" + name + " 年龄是:" + str(age))

结果: 按照添加的顺序输出

  1. 名字是:大娃 年龄是:1
  2. 名字是:二娃 年龄是:2
  3. 名字是:三娃 年龄是:3

发表评论

表情:
评论列表 (有 0 条评论,249人围观)

还没有评论,来说两句吧...

相关阅读