初始面向对象
一.函数式编程和面向对象编程区别
- 函数: 是将某些功能代码封装到函数中,不用重复编写,直接调用函数即可
- 面向对象: 是对函数分类和封装
def email(em,text): """ 发送邮件 :param em: :param text: :return: """ print(em,text) def msg(tel,text): """ 发送短信 :param tel: :param text: :return: """ print(tel,text) def wechat(num,text): """ 发送微信 :param num: :param text: :return: """ print(num,text) # 编写功能:用户购买商品,然后给商家发送提醒 if 1 ==1: msg('13522289159','xxx购买了某个商品') email('592888935@qq.com','xxx购买了某个商品') wechat('xxxxxxx','xxx购买了某个商品')
class Message: def email(self,em,text): """ 发送邮件 :param em: :param text: :return: """ print(em, text) def msg(self,tel, text): """ 发送短信 :param tel: :param text: :return: """ print(tel, text) def wechat(self,num, text): """ 发送微信 :param num: :param text: :return: """ print(num, text) # 编写功能:用户购买商品,然后给商家发送提醒 obj= Message() obj.msg('13522289159', 'xxx购买了某个商品') obj.email('592888935@qq.com', 'xxx购买了某个商品') obj.wechat('xxxxxxx', 'xxx购买了某个商品')
对比:
函数: 定义简单/调用简单
面向对象: 定义复杂/调用复杂 好处:归类/将某些类似的方法(函数)写在一起
总结:
函数式编程可以会比面向对象编程好
python支持两种编程方式
二.类与对象
面向对象编程核心二字即:'对象'
可以把类看做是一个包,包里可以包含多个函数,每个函数实现一个功能
对象则是根据包创建的一个实例,通过实例可以调用包里的函数
定义: class Foo: # 定义了一个类,Foo为类名 def func(): # 在类中编写了一个方法(单独称为函数,放到类中一般都被称为方法) pass 调用: obj = Foo() # 创建了一个对象/实例化一个对象 obj.func() # 通过对象调用类中的方法
class 是关键字,表示你将要创建一个类
创建对象即类名称加括号
提示: 类名定义的时候第一个字母大写,或每个单词的首字母大写(潜规则,可以看出你是不是个老司机)
练习题:
class Account: def login(self): user = input('请输入用户名:') pwd = input('请输入密码:') if user == 'alex' and pwd == 'SB': # SB即:烧饼 print('登录成功') else: print('登录失败') obj = Account() obj.login()
三.三大特性
三大特性:封装/继承/多态
- 封装(顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容)
将相关功能封装到一个类中
class Message: def email(self):pass def msg(self):pass def wechat(self):pass
将数据封装到一个对象中
class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender obj1 = Person('侯明巍',18,'男')
obj2 = Person('房文磊',16,'女')
self 是一个形式参数,当执行 obj1 = Person('侯明巍',18,'男' ) 时,self 等于 obj1
当执行 obj2 = Person('房文磊',16,'女' ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 及 gender 属性,在内存分别开辟两个空间来保存。
""" 完成以下功能: 老狗/20岁/男/上山去砍柴 老狗/20岁/男/开车去东北 老狗/20岁/男/喜欢大宝剑 """ class LaoLi: def __init__(self,name,age,gender): # 特殊的方法,如果 类名(),则该方法会被自动执行 (构造方法) self.name = name self.age = age self.gender = gender def kc(self): data = "%s,%s,今年%s,喜欢上山去砍材" % (self.name, self.gender, self.age) print(data) def db(self): data = "%s,%s,今年%s,喜欢开车去东北" % (self.name, self.gender, self.age) print(data) def bj(self): data = "%s,%s,今年%s,喜欢去做大保健" % (self.name, self.gender, self.age) print(data) obj = LaoLi('老狗',20,'男') obj.kc() obj.db() obj.bj()
- 继承(面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容)
- 单继承
class SuperBase: # 父类,基类 def f3(self): print('f3') class Base(SuperBase): # 父类,基类 def f2(self): print('f2') class Foo(Base): # 子类,派生类 def f1(self): print('f1') obj = Foo() obj.f1() obj.f2() obj.f3()
原则: 先在自己的类中找,找不到去父类找
站的角度不同,对待父类和子类的定义也不同,子类也有可能是别的类的父类
- 多继承
class Base1: def show(self): print('Base1.show') class Base2: def show(self): print('Base2.show') class Foo(Base1,Base2): pass obj = Foo() obj.show() # 左边比右边更亲
总结:
1. 继承编写
2. python支持多继承
3.为什么要有继承: 提高代码的重用性
- 多态(多种形态和多种状态)
python原生支持多态,所有没有特殊性
其Python崇尚“鸭子类型”
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' def Func(args): print args.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj)
由于python函数在传参时没无需指定类型,args可以是多种类型,只要其中有seed方法即可
总结:
以上对面向对象知识总结
- 面相对象是一种编程方式,此编程方式的实现是基于对'类'和'对象'的使用
- 类是一个包,包中包装了多个'函数'供使用
- 对象,根据类创建的实例(即:对象),实例用于调用被包装的类中的函数
- 面向对象的三大特性: 封装/继承/多态
- 封装
归类,将函数放置到一个类中
打包,将数据打包放到一个对象中
- 继承
提高代码的重用性
四.类的成员
成员共分为三类:
1.变量
2.方法
3.属性
1.变量
实例变量(字段)
- 公有实例变量(公有字段)
- 私有实例变量(私有字段)
类变量(静态字段)
- 公有类变量(公有静态字段)
- 私有类变量(私有静态字段)
class Foo: # 类变量(静态字段) country = '中国'
# 私有类变量
__secret = '贪污受贿'
def __init__(self,name,age): # 实例变量(字段) self.name = name
# 私有实例变量 __self.age = age def func(self): pass
什么时候用类变量?
当所有对象中有共同的字段时且要改都改要删都删的时候,可以将实例变量(字段)提取到类变量(静态字段)
私有变量在函数外部是无法访问的
class Foo: def __init__(self,name): # 私有实例变量(私有字段) self.__name = name # 在变量前边加 '__' self.age = 26 def func(self): print(self.__name) obj = Foo('侯明巍') # print(obj.__name) # 无法访问 print(obj.age) obj.func() # 可以让内部的func函数帮助执行内部私有的__name
class Foo: __country = '中国' def __init__(self): pass def func(self): # 内部调用 print(self.__country) print(Foo.__country) # 推荐使用类调用 obj = Foo() obj.func() # 外部无法调用内部私有类变量 # print(Foo.__country) # 外部无法调用
############ 无法访问 class Baer(object): __secret = '贪污受贿' class Foo(Baer): def func(self): print(self.__secret) print(Foo.__secret) obj = Foo() obj.func() ############ 可以访问 class Baer(object): __secret = '贪污受贿' def func1(self): print(Baer.__secret) class Foo(Baer): def func2(self): print(self.__secret) print(Foo.__secret) obj = Foo() obj.func1()
2.方法
1.实例方法
公有实例方法
私有实例方法
2.静态方法
公有静态方法
私有静态方法
3.类方法
公有类方法
私有类方法
class Foo(object): def __init__(self,name): self.name = name # 实例方法 def func1(self): print('实例方法') # 私有实例方法 def __display1(self) print('私有方法') # 静态方法 @staticmethod def func2(): print('静态方法') # 私有静态方法 def __display2(): print('私有静态方法') # 类的方法. cls是类 @classmethod def func3(cls): print(类方法) # 私有类方法 @ classmethod def __display(cls) print('私有类方法')
静态方法总结:
1.编写时:
- 方法上方写 @staticmethod
- 方法参数(self)可有可无
2.调用时:
- 类.方法名() # 推荐
- 对象.方法名()
3.什么时候写静态方法
- 无需使用对象中封装的值的时候
类方法总结:
1.定义时:
- 方法上方写 @classmethod
- 方法的参数:至少有一个cls的参数
2.执行时:
- 类名.方法名() # 默认会把当前类传到参数中
3.什么时候用类方法
- 如果在方法中会使用到当前类,那么久可以使用类方
静态方法/类方法和实例方法的区别?
1.定义:
1.实例方法上方什么也不加
2.静态方法上方加 @staticmethod
3.类方法上方加 @classmethod
2.执行:
1.实例方法是先实例化,再通过对象.方法名
2.静态方法是通过类.方法名
3.类方法是通过类.方法名
3.属性(通过方法改造出来的)
公有属性
私有属性
class Foo(object): def __init__(self): pass # 属性 @property def start(self): return "hell word,I's'赛利亚" # 私有属性 @property def __end(self): return '你好啊,我是赛利亚'
属性总结:
1.编写时
- 方法上方写 @property
- 方法参数: 只有一个self
2.调用时: 无需加括号,直接 对象.方法
3.应用场景: 对于简单的方法,当无需传参且有返回值时,可以使用 @property