面向对象
一.面向对象三大特性
封装 (把多个方法都需要的参数放在init方法中)
封装 (把多个方法都需要的参数放在init方法中)
class f1(object): def __init__(self,name,age,adress,country): self.name=name self.age=age self.adress=adress self.country=country obj=f1('haha',18,'beijing','china')
继承 (多个方法用到共同一个方法就可用继承的模式写,提高代码复用率,简化代码)
class f1(): def func(self): pass class f2(f1): def func1(self): pass class f3(f1): def func2(self): pass obj2=f2() obj3=f3() obj2.func() obj3.func()
多态 (鸭子模型)
class f1(): def __init__(self,m): print(m) obj=f1(1) obj1=f1('haha') obj2=f1([12,123]) obj3=f1({'hah':'123','lala':'321'}) obj4=f1(True) obj5=f1((1,2,3))
二. 类的成员
1. 变量:
- 实例变量(字段)
- 公有实例变量(字段)
- 私有实例变量(字段)
- 类变量(静态字段)
- 公有类变量(静态字段)
- 私有类变量(静态字段)
实例一:
- 实例变量(字段)
- 公有实例变量(字段)
- 私有实例变量(字段)
- 类变量(静态字段)
- 公有类变量(静态字段)
- 私有类变量(静态字段)
实例一:
class Foo: # 类变量(静态字段) country = "中国" def __init__(self,name): # 实例变量(字段) self.name = name def func(self): pass obj1 = Foo('季红') obj2 = Foo('王晓东') Foo.country
派生类无法调用私有字段.
无法访问:class Base(object): __secret = "受贿" class Foo(Base): def func(self): print(self.__secret) print(Foo.__secret) obj = Foo() obj.func()
可以访问:
class Base(object): __secret = "受贿" def zt(self): print(Base.__secret) class Foo(Base): def func(self): print(self.__secret) print(Foo.__secret) obj = Foo() obj.zt()
2.方法:
- 实例方法
class Foo(object): def __init__(self, name): self.name = name # 实例方法 def func(self): print(self.name) obj = Foo('..') obj.func()
- 静态方法
class Foo(object): def __init__(self, name): self.name = name # 静态方法,如果方法无需使用对象中封装的值,那么就可以使用静态方法 @staticmethod def display(a1,a2): return a1 + a2 Foo.display(1,3)
- 类方法
class Foo(object) # 类方法,cls是类 @classmethod def show(cls,x1,x2): print(cls,x1,x2) # 执行类方法 Foo.show(1,8)
面试题: 静态方法/类方法和实例方法的区别?
(1)定义(参数) 静态方法可以不传参数 前面加@staticmethod 类方法必须至少有1个参数cls 前面加@classmethod 实例方法必须有1个参数self (2)调用 静态方法首选类名调用 类名.类方法(首选) 对象.类方法 类方法首选类名调用 类名.类方法(首选) 对象.类方法 实例方法必须用实例化对象去调用 对象.实例方法(唯一调用方法)
3. 属性(通过方法改造出来):
示例:
class Foo(object): def __init__(self): pass @property def start(self): return 1 @property def end(self): return 10 obj = Foo() print(obj.start) print(obj.end)
# 总结:
# 1. 编写时
# - 方法上方写 @property
# - 方法参数:只有一个self
# 2. 调用时:无需加括号 对象.方法
# 3. 应用场景: 对于简单的方法,当无需传参且有返回值时,可以使用 @property
三.嵌套
# 1. 编写时
# - 方法上方写 @property
# - 方法参数:只有一个self
# 2. 调用时:无需加括号 对象.方法
# 3. 应用场景: 对于简单的方法,当无需传参且有返回值时,可以使用 @property
三.嵌套
#3 用面向对象的嵌套表示:学生、班级、老师的关系,并创建相关对象进行嵌套【根据自己的理解编写】; class Teacher(): def __init__(self, name, age, kecheng, xingbie): self.name = name self.age = age self.kecheng = kecheng self.xingbie = xingbie class Banji(): def __init__(self,nianji,num,teacher=None): self.nianji=nianji self.num=num self.teacher=teacher class Student(): def __init__(self,num,name,xingbie,age,banji=None): self.num=num self.name=name self.xingbie=xingbie self.age=age self.banji=banji
teacher=Teacher("老师",'30岁','python','男')
banji=Banji('3年级','10班',teacher)
student=Student("学号12",'嘻嘻','男','18岁',banji)
print(student.num,student.name,student.xingbie,student.age,student.banji.num,student.banji.teacher.name)
四.主动调用其他类的成员
方式一:
class Base(object): def f1(self): print('5个功能') class Foo(object): def f1(self): print('3个功能') Base.f1(self) obj = Foo() obj.f1()
#总结:
#Base.实例方法(自己传self)与继承无关
方式二: 按照类的继承顺序,找下一个.
class Foo(object): def f1(self): super().f1() print('3个功能') class Bar(object): def f1(self): print('6个功能') class Info(Foo,Bar): pass # obj = Foo() # obj.f1() obj = Info() obj.f1()
五.特殊成员
class Foo(object): def __init__(self,a1,a2): self.a1 = a1 self.a2 = a2 def __call__(self, *args, **kwargs): print(11111,args,kwargs) return 123 def __getitem__(self, item): print(item) return 8 def __setitem__(self, key, value): print(key,value,111111111) def __delitem__(self, key): print(key) def __add__(self, other): return self.a1 + other.a2 def __enter__(self): print('1111') return 999 def __exit__(self, exc_type, exc_val, exc_tb): print('22222') # 1. 类名() 自动执行 __init__ obj = Foo(1,2) # 2. 对象() 自动执行 __call__ ret = obj(6,4,2,k1=456) # 3. 对象['xx'] 自动执行 __getitem__ ret = obj['yu'] print(ret) # 4. 对象['xx'] = 11 自动执行 __setitem__ obj['k1'] = 123 # 5. del 对象[xx] 自动执行 __delitem__ del obj['uuu'] # 6. 对象+对象 自动执行 __add__ obj1 = Foo(1,2) obj2 = Foo(88,99) ret = obj2 + obj1 print(ret) # 7. with 对象 自动执行 __enter__ / __exit__ obj = Foo(1,2) with obj as f: print(f) print('内部代码') # 8. 真正的构造方法 class Foo(object): def __init__(self, a1, a2): # 初始化方法 """ 为空对象进行数据初始化 :param a1: :param a2: """ self.a1 = a1 self.a2 = a2 def __new__(cls, *args, **kwargs): # 构造方法 """ 创建一个空对象 :param args: :param kwargs: :return: return object.__new__(cls) # Python内部创建一个当前类的对象(初创时内部是空的.). obj1 = Foo(1,2) print(obj1) obj2 = Foo(11,12) print(obj2)
9.__str__ class Foo(object): def __init__(self): pass def func(self): pass def __str__(self): return "F1" obj = Foo() print(obj,type(obj)) 10.__doc__ class Foo(object): """ asdfasdfasdfasdf """ def __init__(self): pass def func(self): pass def __str__(self): return "F1" obj = Foo() print(obj.__doc__) 11.__dict__ class Foo(object): def __init__(self,name,age): self.name = name self.age = age def func(self): pass obj1 = Foo('刘博文',99) obj2 = Foo('史雷',89) print(obj1.__dict__) # {'name': '刘博文', 'age': 99} print(obj2.__dict__) # {'name': '史雷', 'age': 89} __iter__ # l1是list类的一个对象,可迭代对象 l1 = [11,22,33,44] # l2是list类的一个对象,可迭代对象 l2 = [1,22,3,44] class Foo(object): def __init__(self,name,age): self.name = name self.age = age def func(self): pass def __iter__(self): # return iter([11,22,33,44,55,66]) yield 11 yield 22 yield 33 # obj1是Foo类的一个对象,可迭代对象 """ 如果想要把不可迭代对象 -> 可迭代对象 1. 在类中定义__iter__方法 2. iter内部返回一个迭代器(生成器也是一种特殊迭代器) """ obj1 = Foo('刘博文',99) for item in obj1: print(item)
六.isinstance/issubclass/type
(1)isinstance(对象,类),检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
class Base(object):
pass
class Foo(Base):
pass
obj1 = Foo()
print(isinstance(obj1,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
print(isinstance(obj1,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
obj2 = Base()
print(isinstance(obj2,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
print(isinstance(obj2,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
(2)issubclass(类,类): #检查第一个参数是否是第二个参数的 子子孙孙类
class Base(object):
pass
class Foo(Base):
pass
class Bar(Foo):
pass
print(issubclass(Bar,Base)) # 检查第一个参数是否是第二个参数的 子子孙孙类
(3)type(对象):获取当前对象是由那个类创建。
"""
class Foo(object):
pass
obj = Foo()
print(obj,type(obj)) # 获取当前对象是由那个类创建。
if type(obj) == Foo:
print('obj是Foo类型')
"""
# #### 练习题
"""
class Foo(object):
pass
class Bar(object):
pass
def func(*args):
foo_counter =0
bar_counter =0
for item in args:
if type(item) == Foo:
foo_counter += 1
elif type(item) == Bar:
bar_counter += 1
return foo_counter,bar_counter
# result = func(Foo(),Bar(),Foo())
# print(result)
v1,v2 = func(Foo(),Bar(),Foo())
print(v1,v2)
"""
"""
给你一个参数,判断对象是不是由某一个指定类? type --> type(obj) == Foo
给你一个参数,判断对象是不是由某一个指定类或其父类? isinstance --> instance(obj,Foo)
"""
七.方法和函数
称谓: 类,方法 外,函数 到底方法函数? 对象.xxx --> xxx就是方法 类.xxx --> xxx就是函数 xxx --> xxx就是函数 打印查看: function method 代码检查: from types import MethodType,FunctionType def check(arg): """ 检查arg是方法还是函数? :param arg: :return: """ if isinstance(arg,MethodType): print('arg是一个方法') elif isinstance(arg,FunctionType): print('arg是一个函数') else: print('不知道是什么')
八.反射
getattr(obj,"func") # 根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员。 getattr # 根据字符串的形式,去对象中找成员。 hasattr # 根据字符串的形式,去判断对象中是否有成员。 setattr # 根据字符串的形式,动态的设置一个成员(内存) delattr # 根据字符串的形式,动态的删除一个成员(内存) 应用一: # by luffycity.com from types import FunctionType import handler while True: print(""" 系统支持的函数有: 1. f1 2. f2 3. f3 4. f4 5. f5 """) val = input("请输入要执行的函数:") # val = "f1" # 错误 # handler.val() if hasattr(handler,val): func_or_val = getattr(handler,val) # 根据字符串为参数,去模块中寻找与之同名的成员。 if isinstance(func_or_val,FunctionType): func_or_val() else: print(func_or_val) else: print('handler中不存在输入的属性名') # 正确方式 """ if val == 'f1': handler.f1() elif val == 'f2': handler.f2() elif val == 'f3': handler.f3() elif val == 'f4': handler.f4() elif val == 'f5': handler.f5() """ 应用二: class Account(object): func_list = ['login', 'logout', 'register'] def login(self): """ 登录 :return: """ print('登录111') def logout(self): """ 注销 :return: """ print('注销111') def register(self): """ 注册 :return: """ print('注册111') def run(self): """ 主代码 :return: """ print(""" 请输入要执行的功能: 1. 登录 2. 注销 3. 注册 """) choice = int(input('请输入要执行的序号:')) func_name = Account.func_list[choice-1] # func = getattr(Account,func_name) # Account.login # func(self) func = getattr(self, func_name) # self.login func() obj1 = Account() obj1.run() obj2 = Account() obj2.run()