一、面向对象
1、类与对象
类名要满足大驼峰命名法,每一个单词首字母都大写
(使用dir内置函数,可以查看对象内所有的属性和方法)
__方法名__
格式的方法是 Python
提供的 内置方法 / 属性
序号 | 方法名 | 类型 | 作用 |
---|---|---|---|
01 | __new__ |
方法 | 创建对象时,会被 自动 调用 |
02 | __init__ |
方法 | 对象被初始化时,会被 自动 调用 |
03 | __del__ |
方法 | 对象被从内存中销毁前,会被 自动 调用 |
04 | __str__ |
方法 | 返回对象的描述信息,print 函数输出使用 |
类中的方法第一个参数必须是self
class Cat: def eat(self): print("小猫爱吃鱼") def drink(self): print("小猫要喝水") tom = Cat() tom.eat() tom.drink()
在Python中想给对象增加属性,只需要在 类的外部的代码 中直接通过 .
设置一个属性即可,这种方式虽然简单,但是不推荐使用;
class Cat: def eat(self): print("小猫%s爱吃鱼" % self.name) def drink(self): print("小猫%s要喝水" % self.name) tom = Cat() tom.name = "汤姆" tom.eat() tom.drink()
2、初始化方法
当使用类名()创建对象时,会自动执行:为对象在内存中分配空间、为对象的属性设置初始值;
__init__方法是专门用来定义一个类具有哪些属性的方法,是对象的内置方法;
class Cat: def __init__(self): print("初始化方法") self.name = "" def eat(self): print("小猫%s爱吃鱼" % self.name) def drink(self): print("小猫%s要喝水" % self.name) tom = Cat() tom.eat() tom.drink()
class Cat: def __init__(self, name): print("初始化方法") self.name = name def eat(self): print("小猫%s爱吃鱼" % self.name) tom = Cat("Tom") tom.eat()
3、内置方法
当一个对象从内存中被销毁前,会自动调用__del__方法,对象的生命周期结束
当使用print打印对象变量时,如果希望打印自定义的内容,就可以利用__str__这个内置方法,__str__必须要返回一个字符串
class Cat: def __init__(self, name): self.name = name print("%s来了" % self.name) def __del__(self): print("%s走了" % self.name) def __str__(self): return "我是一只小猫,我叫%s" % self.name tom = Cat("tom") print(tom)
4、封装案例
class Person: def __init__(self, name, weight): self.name = name self.weight = weight def run(self): self.weight -= 0.5 def eat(self): self.weight += 1 def __str__(self): return "我叫%s,我的体重是%.1f" % (self.name, self.weight) xiaomei = Person("小美", 90.0) xiaomei.run() xiaomei.eat() print(xiaomei)
class HouseItem: def __init__(self, name, area): self.name = name self.area = area def __str__(self): return "[%s]占地%.2f" % (self.name, self.area) class House: def __init__(self, house_type, area): self.house_type = house_type self.area = area self.free_area = area self.item_list = [] def __str__(self): return ("户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s" % (self.house_type, self.area, self.free_area, self.item_list)) def add_item(self, item): if item.area > self.free_area: print("%s面积太大,无法添加" % item.name) return self.item_list.append(item.name) self.free_area -= item.area bed = HouseItem("席梦思", 10) print(bed) chest = HouseItem("衣柜", 5) print(chest) table = HouseItem("餐桌", 5) print(table) my_home = House("两室一厅", 100) my_home.add_item(bed) my_home.add_item(chest) my_home.add_item(table) print(my_home)
class Gun: def __init__(self, type): self.type = type self.bullet_count = 0 def add_bullet(self, count): self.bullet_count += count def shoot(self): if self.bullet_count <= 0: print("没有子弹了") return self.bullet_count -= 3 print("[%s]突突突...[%d]" % (self.type, self.bullet_count)) class Soldier: def __init__(self, name): self.name = name self.gun = None def fire(self): # 使用身份运算符is,用于比较对象的内存地址是否一致 if self.gun is None: print("%s还没有枪" % self.name) return print("冲啊...[%s]" % self.name) self.gun.add_bullet(50) self.gun.shoot() AK47 = Gun("AK47") # AK47.add_bullet(50) # AK47.shoot() xusanduo = Soldier("许三多") xusanduo.gun = AK47 xusanduo.fire()
运算符 | 描述 | 实例 |
---|---|---|
is | is 是判断两个标识符是不是引用同一个对象 | x is y,类似 id(x) == id(y) |
is not | is not 是判断两个标识符是不是引用不同对象 | x is not y,类似 id(a) != id(b) |
5、私有属性和方法
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
class Woman: def __init__(self, name): self.name = name self.__age = 18 def secret(self): print("%s的年龄是%d" % (self.name, self.__age)) xiaoyuan = Woman("小圆") xiaoyuan.secret()
在Python中并没有真正意义的私有(伪私有属性/方法),Python解释器会对私有属性和方法名做特殊处理:_类名__属性名
class Woman: def __init__(self, name): self.name = name self.__age = 18 def __secret(self): print("%s的年龄是%d" % (self.name, self.__age)) xiaoyuan = Woman("小圆") print(xiaoyuan._Woman__age) xiaoyuan._Woman__secret()
6、单继承
面向对象三大特性:
封装:根据职责将属性和方法封装到一个抽象的类中
继承:实现代码的重用,相同的代码不需要重复的编写
多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
子类-父类-继承
派生类-基类-派生
class Animal: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") class Dog(Animal): def bark(self): print("叫") class XiaoTianQuan(Dog): def fly(self): print("飞") wangcai = XiaoTianQuan() wangcai.eat() wangcai.run() wangcai.bark() wangcai.fly()
7、方法的重写
class Animal: def eat(self): print("吃") def run(self): print("跑") class Dog(Animal): def bark(self): print("汪汪汪") class XiaoTianQuan(Dog): def fly(self): print("飞") def bark(self): super().bark() print("哈哈哈") wangcai = XiaoTianQuan() wangcai.eat() wangcai.bark() wangcai.fly()
super()就是使用super类创建出来的对象
在Python2时,如果需要调用父类的方法,还可以使用以下方式:父类名.方法(self)
(不推荐使用)
8、间接访问父类私有属性和方法
通过父类公有方法间接访问父类的私有属性和私有方法
class A: def __init__(self, num1): self.num1 = num1 self.__num2 = 2 def __test(self): print("私有方法") def test(self): print(self.__num2) self.__test() class B(A): pass b = B(1) b.test()
9、多继承
class A: def test(self): print("test方法") class B: def demo(self): print("demo方法") class C(A, B): pass c = C() c.test() c.demo()
如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承。
同名方法的调用,是根据Python中的MRO(method resolution order)方法搜索顺序,来决定的;
Python提供的__mro__可以查看方法搜索顺序:
print(C.__mro__)
输出: (<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘object‘>)
__mro__
的输出结果 从左至右 的顺序查找的
10、新式类与经典类
新式类:以object为基类,推荐使用,Python3中没有指定父类,会默认以object为基类,Python3中的类都是新式类
旧式类:不以object为基类,不推荐使用
新式类和旧式类在多继承时会影响到方法的搜索顺序
为了保证代码能在Python2/3运行,编写代码时,如果没有父类,建议统一继承自object
11、多态
不同的子类对象调用相同的父类方法,产生不同的执行结果
以继承和重写父类方法为前提
class Dog(object): def __init__(self, name): self.name = name def game(self): print("%s蹦蹦跳跳" % self.name) class XiaoTianDog(Dog): def game(self): print("%s飞天" % self.name) class Person(object): def __init__(self, name): self.name = name def game_with_dog(self, dog): print("%s与%s快乐的玩耍" % (self.name, dog.name)) dog.game() xtq = XiaoTianDog("哮天犬") wc = Dog("旺财") xm = Person("小明") xm.game_with_dog(xtq) xm.game_with_dog(wc)
传入不同的狗对象实参,就会产生不同的执行效果
12、类属性和类方法
每一个对象 都有自己 独立的内存空间,保存各自不同的属性
多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法内部
类是一个特殊的对象:类对象在内存中只有一份,在程序运行时,类同样会被加载到内存
类对象拥有自己的属性和方法,直接通过 类名. 的方式访问
原文:https://www.cnblogs.com/ysysyzz/p/10923453.html