今天开始了一个新的知识点:面向对象编程
系统提示:找不到对象。。。
内容包含:类、对象、命名规则、封装、继承
类:创建对象
对象:由类创造出来的一个具体存在
由哪一个类创建出来的对象,就拥有在哪一个类中定义的 属性 和 方法
类只有一个,对象可以由很多个
不同的对象之间,属性可能会各不相同
类名要满足大驼峰命名法
使用类名()创建对象的时候,会自动调用初始化方法__init__
__init__方法是专门来定义一个类具有那些属性的方法
__str__方法必须返回一个字符串
在对象的方法内部,是可以直接访问对象的属性的
同一个类创建的多个对象之间,属性互不干扰
被使用的类,通常应该先开发。
在定义属性时,如果不知道设置什么初始值,可以设置为None
None关键字表示什么都没有
表示一个空对象,没有方法和属性,是一个特殊的常量
可以将None赋值给任何一个变量
下面是一个类的封装案例
class Gun: # 枪类 def __init__(self, model): # 枪的型号 self.model = model # 子弹的数量 self.bullet_count = 0 def add_bullet(self, count): self.bullet_count += count def shoot(self): # 判断子弹数量 if self.bullet_count <= 0: print("[%s]没有子弹了。。" % self.model) return # 发射子弹 self.bullet_count -= 1 # 提示发射信息 print("[%s]突突突。。[%d]" % (self.model, self.bullet_count)) class Soldier: # 士兵类 def __init__(self, name): # 姓名 self.name = name # 枪 - 新兵没有枪 self.gun = None def fire(self): # 判断士兵是否由枪 # if self.gun == None: # 身份运算符 "is" / "is not" 。根据PEP8建议,这里应该用"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() # 创建三多 sanduo = Soldier("三多") sanduo.gun = ak47 sanduo.fire() # print(sanduo.gun)
私有属性和私有方法:
class Women: def __init__(self, name): self.name = name # 私有属性:在外界无法被直接访问 self.__age = 18 def __secret(self): # 在对象的方法内部,是可以访问对象的私有属性 print("%s 的年龄是 %d" % (self.name, self.__age)) xiaohong = Women("小红") # 私有属性,无法获取到年龄 # print(xiaohong.__age) # 私有方法同样无法在外界访问 xiaohong.__secret()
补充:伪私有属性和私有方法
在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法
Python 中,并没有 真正意义 的 私有
在给属性、方法命名时,实际是对名称做了一些特殊处理,使得外界无法访问到
处理方式:在名称前面加上 _类名 => _类名__名称
# 私有属性,外部不能直接访问到 print(xiaohong._Women__age) # 私有方法,外部不能直接调用 xiaohong._Women__secret()
如果不适用继承,开发下面所示的案例,会产生大量的重复代码
class Animal: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡") class Dog: def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡") def bark(self): print("汪汪汪") wangcai = Dog() wangcai.eat() wangcai.drink() wangcai.run() wangcai.sleep() wangcai.bark()
下面是继承的案例:
""" 继承的语法 class 类名(父类名): pass """ class Animal: # 父类 def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡") class Dog(Animal): # 子类。子类拥有父类的所有属性和方法。 def bark(self): print("汪汪汪") wangcai = Dog() wangcai.eat() wangcai.drink() wangcai.run() wangcai.sleep() wangcai.bark()
可以这么说:
Dog 类是 Animal 类的子类,Animal 类是 Dog 类的父类,Dog 类从 Animal 类继承
Dog 类是 Animal 类的派生类,Animal 类是 Dog 类的基类,Dog 类从 Animal 类派生
继承的传递性
class Animal: # 父类 -- 动物类 def eat(self): print("吃") def drink(self): print("喝") def run(self): print("跑") def sleep(self): print("睡") class Dog(Animal): # 子类 -- 狗类 -- 继承于动物类 def bark(self): print("汪汪汪") class XiaoTianQuan(Dog): # 子类 -- 哮天犬 -- 继承于狗类 def fly(self): print("我会飞") class Cat(Animal): # 子类 -- 猫类 -- 继承于动物类 def catch(self): print("抓老鼠") xtq = XiaoTianQuan() xtq.fly() xtq.bark() xtq.run() xtq.sleep() xtq.drink() xtq.eat() # 哮天犬和猫之间没有继承关系,不能调用猫类的方法 # xtq.catch()
如果原本父类封装的方法无法满足需求,可以重写方法:
class Animal:… class Dog(Animal):… class XiaoTianQuan(Dog): # 子类 -- 哮天犬 -- 继承于狗类 def fly(self): print("我会飞") # 如果子类中重写了父类的方法 # 在使用子类对象调用方法时,会调用子类中重写的方法 def bark(self): print("我会讲人类的语言") class Cat(Animal):… xtq = XiaoTianQuan() xtq.bark() # ————————————————— # 我会讲人类的语言 # # Process finished with exit code 0 # —————————————————
如果重写方法后,还需要包含父类的方法,使用super(),调用原本在父类中封装的方法
class Animal:… class Dog(Animal):… class XiaoTianQuan(Dog): # 子类 -- 哮天犬 -- 继承于狗类 def fly(self): print("我会飞") # 如果子类中重写了父类的方法 # 在使用子类对象调用方法时,会调用子类中重写的方法 def bark(self): # 需求1:针对子类特有的需求,编写代码 print("我会讲人类的语言") # 需求2:使用super(),调用原本在父类中封装的方法 super().bark() # 需求3:增加其他子类的代码 print("$%^&**&^%^&*(") class Cat(Animal):… xtq = XiaoTianQuan() xtq.bark() # ————————————————— # 我会讲人类的语言 # 汪汪汪 # $%^&**&^%^&*( # # Process finished with exit code 0 # —————————————————
比较尴尬的是,公司机器的环境是Python 2.7,方法重写不支持super(),要用 父类名.方法(self)
# -*- coding: utf-8 -*- class Animal:… class Dog(Animal):… class XiaoTianQuan(Dog): # 子类 -- 哮天犬 -- 继承于狗类 def fly(self): print("我会飞") # 如果子类中重写了父类的方法 # 在使用子类对象调用方法时,会调用子类中重写的方法 def bark(self): # 需求1:针对子类特有的需求,编写代码 print("我会讲人类的语言") # 需求2:使用super(),调用原本在父类中封装的方法 # super().bark() <-- 此处注意,Python2.x不支持super() # 注意:如果使用这种子类调用方法,会出现递归调用 -- 注意,调错可能会死循环 Dog.bark(self) # 需求3:增加其他子类的代码 print("$%^&**&^%^&*(") class Cat(Animal):… xtq = XiaoTianQuan() xtq.bark() # ————————————————— # 我会讲人类的语言 # 汪汪汪 # $%^&**&^%^&*( # # Process finished with exit code 0 # —————————————————
父类的私有属性和私有方法,子类中无法直接访问。但是如果父类中使用公有方法去调用,则可以使用子类间接调用父类的私有属性和私有方法:
class A: def __init__(self): self.num1 = 100 # 创建一个父类的私有属性 self.__num2 = 200 # 创建一个父类的私有方法 def __test(self): print("私有方法:%d,%d" % (self.num1, self.__num2)) def test(self): print("这是父类的共有方法") # 父类的私有属性和私有方法,只有在父类可以调用 # 调用属性 print("这是父类的私有属性:%d" % self.__num2) # 调用方法 self.__test() class B(A): def demo(self): # 子类的对象方法中,不能访问父类的私有属性 # print("访问父类的私有属性 %d" % self.__num2) # 子类的对象方法中,不能访问父类的私有方法 # self.__test() # 访问父类的公有属性 print("子类属性 %d" % self.num1) # 调用父类的公有方法 self.test() pass # 创建一个子类对象 b = B() # 调用 b.demo()
转载请注明:逗比根据地 » 实习日记 2020-01-09