在《面向对象初级篇》中是对面向对象的基本认识:
●面向对象是一种编程方式,此编程方式是基于对 类 和 对象 的使用
●类 是一个模板,模板中包装了多个 "函数" 以供使用.
●对象 ,根据模块创建的实例 , 实例用于调用被包装在类中的函数
●面向对象的三大特性 : 封装 , 继承 , 多态 .
注意:将相关功能封装到类中------将相关数据封装到对象中
类
类的成员可以分成三大类: 字段 ,方法 , 属性
注意: 所有成员中,只有普通字段的内容保存对象中,即 : 根据此类创建了多少对象,在内存就有多少个普通字段.而其他的成员,则都是保存在类中,即 : 无论对象的多少,在内存中只创建一份.
一 . 字段
字段分为 : 普通字段(实例变量) 和 静态字段(类变量).
●普通字段属于----对象
●静态字段属于---类
class Foo: #类变量(静态字段) country = "东北" def __init__(self,place): #实例变量(普通字段) self.place = place def func(self): print("123") #直接访问普通字段 obj = Foo("海南") print(obj.place) obj.func() #直接访问静态字段 print(Foo.country) #obj.country
准则: 实例变量(普通字段)访问时,使用 对象 访问.即 : obj.place
类变量(静态字段)访问时,使用 类 方法(也可以使用对象访问,但是尽量不用对象访问),即 : Foo.country
#易错点 class Foo: country = "东北" def __init__(self,place): self.place = place def func(self): pass obj1 = Foo("海南") obj2 = Foo("重庆") print(obj1.place) #海南 print(obj2.place) #重庆 print(Foo.country) #东北 ####练习1. obj1.place = "云南" print(obj1.place) #云南 print(obj2.place) #重庆 ####练习2. obj1.country = "广西" print(obj1.country) #广西 print(obj2.country) #东北 ####练习3. Foo.country = "上海" print(obj1.country) #上海 print(obj2.country) #上海
什么时候使用类变量呢:
当所有对象中有共同的字段时且要同时修改或删除的时候,可以讲 实例变量(普通字段) 提取到 类变量(静态字段).
二 . 方法
方法分为 : 普通方法 , 静态方法 , 类方法 . 三中方法在 内存中都归属于类 ,区别在于调用方式不同.
●普通方法 : 有 对象 调用:至少一个 self 参数,执行普通方法时,自动将调用该方法的对象赋值给self
●静态方法 : 由 类 调用, 无默认参数
●类方法 : 有 类 调用 ,至少一个 cls 参数,执行方法时,自动将调用该方法的类赋值给cls.
#方法的定义和使用 class Foo: def __init__(self,name): self.name = name def func(self): #无需写方法 print("func") def func1(self): #定义普通方法,至少有一个 self 参数 print(self.name) @staticmethod #静态方法,无默认参数.无需使用对象中封装的值 def func3(a1,a2): return a1 + a2 @classmethod #类方法,至少有一个 cls 参数 def func4(cls,x1,x2): print(cls,x1,x2) obj = Foo(123) obj.func() #调用普通方法 obj = Foo("张三") obj.func1() #调用静态方法 print(Foo.func3(1,2)) #调用类方法 Foo.func4(1,2)
总结:
1.静态方法: 编写时------方法上面写@staticmethod 方法参数可有可无
调用时------类.方法名() 对象.方法名()---(尽量不用这个)
什么时候写静态方法-----无需调用对象中已封装的值.
2.类方法: 编写时------方法上面写@classmethod 方法至少有一个 cls 参数
调用时------类名.方法名() #默认会将当前类传到参数中.
什么时候使用------如果在方法中会使用到当前类,.
123
三 . 属性
属性其实就是通过 普通方法 改造出来的.
#原面向对象方法和属性的对比 class Foo: def __init__(self): pass def func(self): return 10 def func1(self): return 20 obj = Foo() print(obj.func()) print(obj.func1()) ##############属性############## class Foo: def __init__(self): pass @property #属性定义 def func(self): return 10 @property def func1(self): return 20 obj = Foo() #调用属性 print(obj.func) print(obj.func1)
总结:
●编写时 : 在普通方法的基础上加上 @property
●只有一个参数 self
●调用时,无需 括号
方法: obj.func()
属性: obj.func
●应用场景 : 对于简单的方法,当无需传参且有返回值时,可以使用属性
实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括: 根据用户请求的当前页和总数据条数计算出 m 和 n 根据m 和 n 去数据库中请求数据 class Pagenation(object): """ 处理分页相关的代码 """ def __init__(self,data_list,page,per_page_num=10): """ 初始化 :param data_list: 所有的数据 :param page: 当前要查看的页面 :param per_page_num: 每页默认要显示的数据行数 """ self.data_list = data_list self.page = page self.per_page_num = per_page_num @property def start(self): """ 计算索引的起始位置 :return: """ return (self.page-1) * self.per_page_num @property def end(self): """ 计算索引的结束位置 :return: """ return self.page * self.per_page_num def show(self): result = self.data_list[self.start:self.end] for row in result: print(row) data_list = [] for i in range(1, 901): data_list.append('alex-%s' % i) while True: # 1. 要查看的页面 page = int(input('请输入要查看的页码:')) obj = Pagenation(data_list,page) obj.show()
四 . 类成员的修饰器
类 的成员可以分成 3 类 6个,对于每一个成员而言都有两种形式.
● 公有成员 , 在任何地方都能访问
● 私有成员 , 只有在类的内部才能访问
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线.(特殊成员除外,__init__).
私有成员和公有成员的访问限制不同:
静态字段
● 公有静态字段 : 类可以访问,类内部可以访问,派生类(子类)可以访问
● 私有静态字段 : 仅类内部可以访问
class C: name = "公有静态字段" def func(self): print C.name class D(C): def show(self): print C.name C.name # 类访问 obj = C() obj.func() # 类内部可以访问 obj_son = D() obj_son.show() # 派生类中可以访问
class C: __name = "公有静态字段" def func(self): print C.__name class D(C): def show(self): print C.__name C.__name # 类访问 ==> 错误 obj = C() obj.func() # 类内部可以访问 ==> 正确 obj_son = D() obj_son.show() # 派生类中可以访问 ==> 错误
普通字段
● 公有普通字段 : 对象可以访问,类内部可以访问,派生类可以访问
● 私有普通字段,仅类内部可以访问
ps: 如果想要强制访问私有字段 ,可以通过 对象._类名__私有字段名 不建议使用
class C: def __init__(self): self.foo = "公有字段" def func(self): print self.foo # 类内部访问 class D(C): def show(self): print self.foo # 派生类中访问 obj = C() obj.foo # 通过对象访问 obj.func() # 类内部访问 obj_son = D(); obj_son.show() # 派生类中访问
class C: def __init__(self): self.__foo = "私有字段" def func(self): print self.foo # 类内部访问 class D(C): def show(self): print self.foo # 派生类中访问 obj = C() obj.__foo # 通过对象访问 ==> 错误 obj.func() # 类内部访问 ==> 正确 obj_son = D(); obj_son.show() # 派生类中访问 ==> 错误
方法 和 属性的访问和上述字段访问方式相同,都是 : 私有成员只能在类内部使用.
面向对象的嵌套
面向对象的嵌套和函数的嵌套,列表的嵌套相似..
创建三个学校且三个学校的设施内容等都是一致. """ class School(object): def __init__(self, name, address): self.name = name self.address = address def speech(self): print('讲课') obj1 = School('清华大学北京校区', '海淀校区') obj2 = School('清华大学上海校区', '浦东校区') obj3 = School('清华大学深圳校区', '南山校区') class Teacher(object): def __init__(self, name, age, salary): self.name = name self.age = age self.__salary = salary #工资应该是私有的 self.school = None #在老师没去学校的时候是没有教学的 t1 = Teacher('张三', 36, 35000) t2 = Teacher('李四', 45, 55000) t3 = Teacher('王五',28, 20000) # ############## 老师分配校区 t1.school = obj1 t2.school = obj1 t3.school = obj2 # #################################### # 查看t1老师,所在的校区名称/地址 print(t1.school.name) print(t1.school.address) print(t1.name) print(t1.age) t1.school.speech()