No.009-Python-学习之路-Day6-面向对象的特性及语法
面向对象介绍
何为编程?
程序员按照特定的语法、数据结构及算法组织代码,以此来告诉计算机如何执行任务的过程;
编程范式[Programming paradigm]
从不同编程方式中归纳总结出来的编程方式类别,包含面向过程,面向对象,函数式编程等;
面向过程[Procedure Oriented]
通过一组指令,一步步告诉电脑怎么做,依赖Procedure[过程];
核心思想:大问题->小问题->更小的问题->(可以在一个小范围内解决);
问 题:从上到下,逐步依赖,改一个位置,相关依赖均要修改;
使用场景:面向过程比较适合简单脚本,一次性任务等场景使用,效率较高;
面向对象[OOP-Object Oriented Programming]
通过类与对象创建各种模型来实现对真实世界的描述;世界万物,皆可分类;世界万物,皆为对象;
只要是对象,就肯定属于某个品类;
只要是对象,就肯定有属性<静态属性,动态属性>;
在描述现实世界时,需要按照现实世界的规则来,所以需要搭建一个框架,才能够对某个事物进行描述;
优 势:易维护,易扩展,编程效率高,使别人更易理解,是团队开发变得从容;
语法
包含:属性、方法、构造函数、析构函数、私有方法、私有属性、类变量、实例变量。
class Dog: # 定义一个类 Dog 类名
n = 123 # 类变量<存在类的内存中>
# 类变量,所有实例公用的属性,可以修改,节省开销
name = "Class name"
name_list = ['11', '22', '33']
# 在实例化时,需要赋予的属性
# 构造函数:
# 作用:在实例化时,做一些类的初始化的工作<实例赋名字,传参数之类>
def __init__(dog_var, name): # dog_var用来接收实例名,如dog1, dog2,dog3
dog_var.name = name # dog_var.name属于实例变量<静态属性>,作用域是实例本身
# 实例变量用来描述类的不同实例的不同属性
dog_var.__owner = "Bruce" # 私有属性
# 私有方法同理,def __siyou(self): pass
# 类的方法,功能<动态属性>
def bulk(dog_var1): # dog_var1也是用来接收实例名,如dog1,dog2,dog3
print("%s Wang wang wang!!!" % dog_var1.name)
def get_owner(self):
print(self.__owner)
def __del__(self): # 析构函数
#print("%s was dead!!" % self.name)
#print("I miss you %s." % self.name)
pass
# 生成对象dog1-3
# 实例化(初始化一个类,造了一个对象),把一个类变为一个实例的过程;
# 对象又称为Dog类的一个实例
dog1 = Dog('Xilou')
dog2 = Dog("QiuQiu") # 生成了一具体的狗狗
dog3 = Dog("Buck")
# 让狗叫
dog1.bulk() # 等价于Dog.bulk(dog1)
Dog.bulk(dog1) # 等价于dog1.bulk()
del dog1 # 删除实例<摘门牌号>,删除时调用析构函数__del__(self):
dog2.bulk()
dog3.bulk()
#### 类变量与实例变量的介绍与区别
print(Dog.n) # 类变量=>未实例化即可调用
print(Dog.name)
dog4 = Dog("Mengmeng")
print(dog4.n)
print(dog4.name) # 变量先找实例本身,如果没有则找类变量的;
dog5 = Dog("Doudou")
dog5.name = "豆豆" # 实例属性可以修改
dog5.kind = 'little dog' # 为实例新增属性
del dog5.name # 删除实例属性
print(dog5.name, dog5.kind)
dog4.n = 10 # 由结果推断,实例类变量的修改,实际是在实例内存内新建dog4.n=10这个变量;
dog6 = Dog("NianNian")
print(dog4.n, dog5.n, dog6.n) # dog4实例的类变量变更,dog5及dog6未做变更;
dog4.name_list.append('55')
print(dog4.name_list)
dog4.name_list = [333]
dog4.name_list.append(222)
print(dog4.name_list)
Dog.n = "类修改" #
# dog4不受影响,原因之前修改在实例中新建了同名的实例变量
# dog5及dog6调用类变量,所以修改类变量,返回值跟着修改
print(dog4.n, dog5.n, dog6.n)
print(dog5.name_list)
dog5.get_owner()
#####
# 析构函数:在实例释放、销毁的时候自动执行的,通常用于做一些收尾工作<关闭一些数据库链接,打开的临时文件等>;
# python判断变量是否在用-->变量名在则在用,变量不在则不再用-->不在用则从内存中回收;
#####
# 私有方法,私有属性:外部<实例之外>无法访问,只能内部访问<实例内部的方法>;
# 用于类的封装;
dog10 = Dog('XiLou Lee')
print(dog10.__owner) # 直接访问无法访问
dog10.get_owner() # 调用方法访问
#####
实例的生成过程
特性
类[class]
即分类,对一类拥有相同属性<静态属性,动态属性-即方法>的对象的抽象;
对象[object]
即是一个类实例化后的实例;类是对象的抽象,对象是类的特例;
封装[Encapsulation]
封装就是把抽象的数据和对数据进行的操作封装在一起,数据被保存在内部,程序的其他部分只有通过授权的操作(成员方法等)才能对数据进行操作;
继承[Interitance]
一个类可以派生出特殊的子类,则原有类为父类,而父类的属性及方法可以被子类继承;
# 父类-人类 class People: #经典类 #标准写法 class People(object): # 新式类<多继承的方法变了> def __init__(self, name, age): self.name = name self.age = age def eat(self): print("%s is eating." % self.name) def sleep(self): print("%s is sleeping" % self.name) def talk(self): print("%s is talking" % self.name) # 子类1-男人 class Man(People): def __init__(self, name, age, size): # 对构造函数进行重构,实例化时,实际的调用 People.__init__(self,name, age) # 所以,需要获取将父类构造函数的变量 # 并调用父类的构造函数 # People.是经典类的写法 # super(Man, self).__init__(name.age) 等价于上面的调用,作用在父类<People>的名称变更时,不需要更改 # super是新式类的写法,用的更多; self.size = size def piao(self): print("%s is piaoing....20s...done." %self.name) def sleep(self): People.sleep(self) print("%s is shout." % self.name) def get_size(self): print("%s's size is %s." % (self.name, self.size)) # 子类2-女人 class Woman(People): def get_birth(self): print("%s can born a baby...." % self.name) m1 = Man("Bruce", "22", "200") m1.eat() # 继承父类的方法 m1.piao() # 子类新增的方法 m1.sleep() # 重构父类的方法 m1.get_size() w1 = Woman("Ling", '35') w1.get_birth() ##### # 新式类及经典类,对于我们有影响的,主要体现在继承上; #####
多继承方式:
# 父类-人类 class People(object): def __init__(self, name, age): self.name = name self.age = age self.friends = [] def eat(self): print("%s is eating." % self.name) def sleep(self): print("%s is sleeping" % self.name) def talk(self): print("%s is talking" % self.name) # 父类-关系 class Relation(object): def make_friends(self, obj): print('%s is making friends with %s' %(self.name, obj.name)) self.friends.append(obj) # 子类1-男人 class Man(People, Relation): def __init__(self, name, age, size): super(Man, self).__init__(name, age) self.size = size def piao(self): print("%s is piaoing....20s...done." %self.name) def sleep(self): People.sleep(self) print("%s is shout." % self.name) def get_size(self): print("%s's size is %s." % (self.name, self.size)) # 子类2-女人 class Woman(People, Relation): # 多继承顺序是从左到右 def get_birth(self): print("%s can born a baby...." % self.name) m1 = Man("Bruce", 22, 2000) w1 = Woman("Lee", 23) m1.make_friends(w1) # 为什么传obj,人只能跟人交朋友,不能和字符串呀!!!! print(m1.friends) # m1的friends列表中有w1这个人 print(m1.friends[0].name) # 获取m1朋友w1的名字,如果用字符串,就没有联系了呀; ##### # 新式类及经典类,对于我们有影响的,主要体现在继承的多继承这方面; # 为什么要进行多继承: # 因为一样东西可能同时属于两个类;或者拥有该种特质; # 多继承顺序是从左到右,构造函数也是这么执行的;(广度优先<新式类>),深度优先<经典类&Python2>;
#####
多态[Polymorphism]
即,一个接口多种实现;
指一个引用在不同情况下的多种状态;
指通过指向父类的指针,来调用在不同子类中实现的方法;
def animal_bulk(obj): # 统一的一个接口 obj.bulk() class Animal(object): def __init__(self, name, age): self.name = name self.age = age @staticmethod def all_bulk(obj): # 统一的一个接口 obj.bulk() class Dog(Animal): def __init__(self, name, age): super().__init__(name, age) def bulk(self): print("Woof Woof!!") class Goat(Animal): def __init__(self, name, age): super().__init__(name, age) def bulk(self): print("Mian......") dog1 = Dog("QiuQiu", 12) goat1 = Goat("ShanDa", 2) # 静态类方法写法 Animal.all_bulk(dog1) Animal.all_bulk(goat1) # 类外函数调用 animal_bulk(dog1) animal_bulk(goat1)
特性总结:
封装是为了隐藏实现细节,使得代码模块化;
继承可以扩展已存在在的代码模块(类);
封装和继承均为了一个目的:代码的重用;
而多态为了实现另外一个目的-接口重用,为了类在继承和派生的时候,保证使用‘家谱’中任一类的实例和某一属性时的正确调用;
end