目录
OOP编程:Object-Oriented Programming 面向对象编程,有三个基本特征——封装、继承、多态。
为了让程序更易用,经常需要将多种数据、代码语句等封装为函数、模块等,面向对象即需要对数据和代码同时做封装。Python中的对象,即可以认为:
对象=属性+方法
其中,对象的特征称为“属性”,对象的行为称为“方法”。
Python中,使用类(class)来定义对象的属性和方法,实用类创建的对象则称为这个类的一个实例(instance),两者定义如下:
实例对象继承了类定义的属性和方法,即实例可以调用类定义的变量和函数;
实例对象单独记录自己的数据,修改实例对象某个变量后,其他实例对象不因此而改变;
实例对象可以在类的基础上增加新的赋值语句,并可以通过 dir() 查询;
- #类-tank
- class tank:
- Name = 'ZTZ-99A'
- Members = ['张三','李四','王五']
-
- def __init__(self,Armor=80,HP=100,Gun=125,Armor2=0,Gun2=0):
- self.Armor = Armor
- self.HP = HP
- self.Gun = Gun
- self.TargetArmor = Armor2
- self.TargetGun = Gun2
-
- def attack(self):
- damage = self.Gun - self.TargetArmor
- print(f'发起进攻,造成伤害{damage}')
-
- def defend(self):
- damage = self.TargetGun - self.Armor
- print(f'进行防御,受到伤害{damage}')
- if (self.HP - damage) <= 0:
- print('已阵亡')
- else:
- print(f'剩余血量{self.HP-damage}')
-
- #声明实例 tankNo1
- tankNo1 = tank()
-
- #可以调用类定义的变量和函数,并对其中变量数值做修改
- tankNo1.Name
- 'ZTZ-99A'
- tankNo1.attack()
- 发起进攻,造成伤害125
- tankNo1.TargetGun = 105
- tankNo1.defend()
- 进行防御,受到伤害25
- 剩余血量75
-
- ##声明实例 tankNo2
- tankNo2 = tank(Armor2=90,Gun2=120)
- tankNo2.attack()
- 发起进攻,造成伤害35
-
- #修改 tankNo2 实例数据,不影响 tankNo1 实例中数据
- tankNo2.Name = 'ZTZ-96A'
- tankNo2.Name
- 'ZTZ-96A'
- tankNo1.Name
- 'ZTZ-99A'
-
- #实例对象可以在类的基础上增加新的赋值语句,并可以通过 dir() 查询
- tankNo2.Ammunition = 50
- tankNo2.Ammunition
- 50
- dir(tankNo2)
- ['Ammunition', 'Armor', 'Gun', 'HP', 'Members', 'Name', 'TargetArmor', 'TargetGun', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'attack', 'defend']
在Python中,整型变量是整数类的实例对象,字符串变量是字符串类的实例对象,列表、元组、字典、集合也类似。
- x = 100
- type(x)
- <class 'int'>
- dir(x)
- ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
- x.real
- -1
- x.imag
- 0
通常,类中所有方法(静态方法除外)的第一个参数,即 self 参数;
同一个类可以生成无数个实例对象且各自独立,self 即代表类所创建的实例;
self 用于将对象自身的引用作为第一个参数传给方法,帮助 Python 知道应该去操作类生成的哪个对象的方法;
self 参数也可以使用其他参数名,但通常默认使用 'self'。
- class test:
- def printself(self):
- print(self)
-
- x = test()
-
- #self 和实例是同一个对象
- x.printself()
- <__main__.test object at 0x000001CBCA8A0CD0>
- x
- <__main__.test object at 0x000001CBCA8A0CD0>
__init__() 方法又称为构造方法,是Python中的又一种魔法方法,也是类中最常用的方法;
__init__() 方法在实例对象创建时自动调用,并实现各类初始化传参、操作;
__init__() 方法重写后添加的形参,如没有默认值,则在创建实例对象时必须填写实参,否则报错;
__init__() 方法只能返回 None,返回其他对象报错。
- #创建重写 __init__() 方法的类
- class Test:
- def __init__(self, name, date, times):
- self.name = name
- self.date = date
- self.times = times
-
- def operater(self):
- print(f'{self.name}在{self.date}去了{self.times}次小卖部!')
-
-
- #创建实例对象时,填入实参,完成初始化
- test1 = Test('小明','星期一','5')
- test1.name
- '小明'
- test1.operater()
- 小明在星期一去了5次小卖部!
-
- #创建实例对象时,部分参数未赋值,报错
- test2 = Test('小红','2022.1.1')
- Traceback (most recent call last):
- File "<input>", line 1, in <module>
- TypeError: __init__() missing 1 required positional argument: 'times'
-
- #只能返回 None,返回其他对象报错
- class Xtest:
- def __init__(self):
- return 'hi'
-
- testx = Xtest()
- Traceback (most recent call last):
- File "<input>", line 1, in <module>
- TypeError: __init__() should return None, not 'str'
一般面向对象编程语言,都会区分公有和私有数据类型;
Python 中默认对象的属性和方法都是公开的,可以直接通过点操作符 '.' 进行访问;为了实现私有变量和函数,Python 采用 Name Mangling(名字改编)技术,做了部分实现;
Python 中的私有变量或函数,即在变量或函数名前加上 '_' 下划线,添加下划线后,变量/函数名外界无法直接访问;
但 Python 采用的 Name Mangling(名字改编),实际上是把 '__变量/函数名',改编为了 '_类名__变量/函数名',实际上仍可以在外部通过后一种格式进行访问,是一种伪私有变量。
- #定义包含内部变量和内部函数的类
- class Test:
- __testinfo = 'testinfo'
-
- def __testfunc(self):
- print(f'{self.__testinfo}')
-
-
- #外部直接访问内部变量,失败
- test1 = Test()
- test1.__testinfo
- Traceback (most recent call last):
- File "<input>", line 1, in <module>
- AttributeError: 'Test' object has no attribute '__testinfo'
-
- #外部直接访问内部函数,失败
- test1.__testfunc()
- Traceback (most recent call last):
- File "<input>", line 1, in <module>
- AttributeError: 'Test' object has no attribute '__testfunc'
-
- #外部访问改编后的内部变量,成功
- test1._Test__testinfo
- 'testinfo'
-
- #外部访问改编后的内部函数,成功
- #内部函数可以直接调用内部变量,不需要使用改编后的变量名
- test1._Test__testfunc()
- testinfo