10 Python 基础 面向对象编程

本节内容:

    1、介绍

    2、 面向对象的三大特性:构造方法、继承多继承、 多态

    3、类成员、静态字段 、静态方法、类方法、 属性。

    4、成员修饰符、特殊成员

    5、异常处理 、反射、单例

 

一、介绍: 

  适用场景; 先按函数式编程。如果多个函数式编程中,有一些相同参数时,转换成面向对象编程面向对象编程是最有 效的软件编写方法之一,在面向象编写过程中 你编写表实现的中的事务和情景的类,并基于这些类创建对象。编写类时,你定义一大类对象都有用的通用行为,基于类创建对象时每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。使用面向对象编程可模拟现实场景。

    根据类来创建对象被称为实例化,这能够让你使用类的实例。

    面向对象编程有助于你像程序员那样看世界,还可以帮助你真正明白自己编写的代码:不仅是各行代码的作用,还有代码背后更宏大的概念。

创建和使用类   class  关键字  叫类  后面跟得是类名  用驼峰体命名

# class 类名:
#     def 方法名(self,age)
#     print(age)
# 
# 中间人 = 类名              #中间人 等于对象      对象也成为类,的实例(实例化)    后面还会讲单例
# 中间人.方法名(18)         这就执行了方法里的print(age)
View Code
class Wk():      #面向对象  后面跟得是类
    def abc(self,age):    #名字叫abc的方法   第一个参数必须是self
        print(age)
        return 1
mm = wk()#创建中间人  调用方法     因为不可以直接调用里面的方法
ret = mm.abc(18)     #执行
print(ret)     #也能查看返回值
View Code
#self:代指调用的方法 对象 (中间人)
class Wk:
    def mm(self,age):
        print(self,age)
nb = Wk()
print(nb)
nb.mm(11)
nb2 = Wk()
print(nb2)
nb2.mm(666)
View Code

  self  代指对象     对象就是中间人    永远是执行方法的调用者   在对象里面传值   就是封装    然后引出 init方法(构造方法)

 

class Wk:
    def mm(self,age):
        print(self,self.name,self.age,age)
nb = Wk()
nb.name = 'wangkuan'      #把值放到nb对象里 就是封装
nb.age = 18
nb.mm(666)   #传入最后那个age


nb2 = Wk()
nb2.name = 'yx'
nb2.age = 18
nb2.mm(888)
View Code

二、面向对象编程

2.1构造方法

           特殊作用:

                    在 nb = 类名()     内部做了两件事情    :1 创建对象

                                                                                  2 通过对象执行类中的一个特殊方法

__init__  开头末尾各有两个下划线 这是一种约定,避免Python默认方法,与普通方法发生名称冲突。

class Bar:
    def __init__(self):  #self   就是  z 
        print('123')

z = Bar()     #只要创建对象 后面加括号  Python就会自动执行  __init__   方法

print(z)

  

利用init方法 给里面传值 调用 shou 执行__init__ 里的方法 输出 姓名 年龄 血型

class Jianjie:
    def __init__(self,name,age,):
        self.n = name
        self.a = age
        self.xue = 'o'
        
    def shou(self):
        print('%s-%s-%s' % (self.n, self.a,self.xue))

wk = Jianjie('王宽',18)
wk.shou()
wsh = Jianjie('王森浩',22)
wsh.shou()
View Code

 

2.2继承:

  就和现实中的一样继承父类,父亲有的可以继承,也可以不继承,比如父亲抽烟,儿子就不抽,怎么就不继承了 父亲的了,儿子重写,写成一样的,就用儿子 的,因为,先用自己的,自己的没有才找父亲的

官方 介绍:编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的 特殊版本 ,可以使用继承。 一个类继承另一个类时,它将自动获得另一个类的所有属性和方法:原有的类称为父类,而新类称为子类。子类继承的父类的所有属性和方法 ,同时还可以自己定义自己的属性和方法。

 

class Gramps:     #爷爷
    def 喝花酒(self)::
    pass


class Father(Gramps):    #父亲继承他爸   孩子他爷
    def 抽烟(self):
        pass
    def 喝酒(self):
        pass
    def 烫头(self):
        pass



class Son(Father):      #儿子 继承父亲
    def 保健(self):
        pass

s = Son()
s.保健()
s.喝花酒()          #都继承了就可以执行爷爷的了
View Code
class F:
    def w(self):
        print('w,w1')


class Z(F):
    def k(self):
        print('k,k1')


m = Z()
m.w()
View Code
class F1:
    def a(self):
        print('f.a1')
class F2(F1):
    def a(self):
        print('f.a2')

class F3(F2):
    def a1(self):
        print('f.a3')



class S1:
    def b1(self):
        print('s.b1')


class S2(S1):
    def b2(self):
        print('s.b2')
View Code 

  继承   不用父级  的

 

class F:
    def w(self):
        print('w,w1')

    def w2(self):
        print('ss')


class Z(F):
    def k(self):
        print('k,k1')

    def w2(self):      #这就用自己的
        print('qq')

m = Z()
m.w2()
View Code

  

介绍

 

class F:
    def w(self):
        print('w,w1')
    def w2(self):
        print('ss')


class Z(F):
    def k(self):
        print('k,k1')
    def w2(self):

        print('qq')
m = Z()
m.k()       # k 中的self是形参 代指m

m.w()       # self  用于指调方法的调用者
View Code

又想执行自己的又想执行父亲的

 

class F:
    def w(self):
        print('w,w1')

    def w2(self):
        print('ss')


class Z(F):
    def k(self):
        print('k,k1')

    def w2(self):

        super(Z,self).w2()        #执行父类中的w2方法
        # F.w2(self)                 #两种方法   推荐用第一种
        print('qq')

m = Z()
m.w2()    
View Code

  

默认  多继承先从左开始    一条路走到黑

 

class F1:
    def a(self):
        print(111)

class F2:
    def a(self):
        print(222)

class C(F1,F2):      #先从左开始
    def w(self):
        print(3333)

obj = C()
obj.a()
View Code

假设一种现象 S2继承 S1  F3   都有一个共同的根  F    测试什么规律

结果就是  同一个根时   根最后执行

 

class F:
    def a(self):
        print('f.a1')
class F2(F):            #到了根这就不往上找了   往回找S1   如果S1没有 在找根
    def a2(self):
        print('f.a2')

class F3(F2):
    def a1(self):
        print('f.a3')



class S1(F):
    def a(self):
        print('s.b1')


class S2(F3,S1):     #先从左侧开始找
    def b(self):
        print(123)


obj = S2()
obj.a()
View Code

 

 

 重点   self  是谁

 

class AAAAA:
    pass

class BBBBB(AAAAA):
    def w(self):
        print(1111)


        self.m()
#重点在这   m  88888 不执行,执行下面本身的 DDDDD  注意self   是本身的EEEEE     E 下面本身有m



    def m(self):       #不会先执行这的m   先回自己的EEEEEE找  左侧优先  执行DDDDD下的m
        print(88888)

class CCCCC(BBBBB):
    def k(self):
        print(2222)

class DDDDD:
    def m(self):
        print(666666)

class EEEEE(DDDDD,BBBBB):
    def k(self):
        print(33333)

obj = EEEEE()
obj.w()
View Code

 

2.3多态

其他语言创建一个变量时候,要必须指定这个变量是什么类型的(强类型的)

Python  >>> 原生多态

 

三、类成员  :字段、方法、属性

    3.1字段 :普通字段、保存在对象中,执行只能通过对象访问。

    self.name = name   

 

class Foo():
    def __init__(self,name):
        self.name = name

obj = Foo('王宽')
r = obj.name
print(r)
View Code

  

 3.1、静态字段:保存在类中,执行时 可以通过对象访问,也可以通过类访问

   不占内存

 

class Gj:
    chaini = '中国'               #静态字段  保存在类中 由类直接调用  类似全局变量
    def __init__(self,name):
        self.name = name

shanxi = Gj('山西')
hebei = Gj('河北')
print((Gj.chaini),(shanxi.name))
print((Gj.chaini),(hebei.name))

print(shanxi.name)
View Code

  

 3.2方法    

普通方法:保存在类中,由对象来调用      self =》 对象

 

class F:
    def bar(self):
        print('abc')

obj = F()
obj.bar()
View Code

3.2静态方法:保存在类中,由类直接直接调用 不用self 方法

 

#静态方法
class AA:
    @staticmethod    #保存在类中 由类直接调用   不用self 方法  self 不用传值
    def sat():
        print('王宽')

AA.sat()
View Code

3.2类方法:保存在类中,由类直接调用  cls=》当前类

 

#类方法  保存在类中 有类直接调用
class MM:
    @classmethod      #保存在类中 由类直接调用 cls==》当前类
    def kk(cls):     #里面要写 cls     cls  是类名
        print('wangkuan')
MM.kk()
View Code

  

3.3属性  

       特性:定义像是方法 通过字段的形式访问 

 

class AA:
    @property     #属性 特性   定义像是方法  通过字段的形式访问
    def k(self):
        print(123)
        return 1
m = AA()
r = m.k             #如果是方法访问  就得加括号
print(r)
View Code

分页 好看    用属性  好看

 

class Pargination:
    def __init__(self,current_page):
        try:
            p = int(current_page)
        except Exception as e:
            p = 1
        self.page = p

    @property    #   把括号减了  为了好看
    def start(self):
        val = (self.page-1)*10
        return val
    @property
    def end(self):
        val = self.page*10
        return val
li = []
for i in range(1000):
    li.append(i)

while True:
    p = input('请输入查看的页码:')
    obj = Pargination(p)

    print(li[obj.start:obj.end])
View Code

四、成员修饰符         

私有成员:__字段名    无法直接访问,只能间接访问。

不能调用例子

 

class F:
    def __init__(self,name,age):
        self.n = name
        self.__a = age           #私有成员


obj = F('王宽',18)

print(obj.n)
#obj.__a          私有成员外部不能访问
View Code

  

间接

 

#    内部调用方法
class F:
    def __init__(self,name,age):
        self.n = name
        self.__a = age           #私有成员

    def shou(self):            #只有内部调用
        return self.__a
obj = F('王宽',18)
print(obj.n)
ret = obj.shou()
print(ret)
View Code

静态字段   调用

 

class F:
    __v = 88888         #静态字段
    def __init__(self):
        pass
    def shou(self):
        return self.__v
obj = F()

r = obj.shou()
print(r)
View Code 

静态方法     调用不用实例化对象,类  点  方法名 括号就行A.b()  方法前面加个装饰器

 

# #静态方法   调用
class F:
    __v = '88888'
    def __init__(self):
        pass
    @staticmethod
    def shou():

        return F.__v


F.shou()
View Code 

 普通方法  调用

 

class Foo:
    def __f1(self):           #外面不能直接访问
        return 123

    def f2(self):
        r = self.__f1()
        return r

obj = Foo()
s = obj.f2()
print(s)
View Code

不能访问父级里的私有成员

 

class F:
    def __init__(self):
        self.ge = 123
        self.__gene = 123               #私有 外部无法直接访问

class S(F):
    def __init__(self,name):
        self.name = name
        self.__age = 21             #私有 外部无法直接访问
        super(S,self).__init__()

    def show(self):
        print(self.name)
        print(self.__age)
        print(self.ge)
        # print(self.__gene) #不能访问父级里的 私有成员

obj = S('wangkuan')
obj.show()
View Code

  

4.1特殊成员  

__init__    类()      自动执行类里面的__init__方法

__call__   对象()         创建对象然后  对象.括号自动执行类里面的__call__        类 ()()两括号  自动执行 init  call 都执行

__int__   int(对象)

__str__   str()    print时  对象的str()方法   获取返回

__iter__   如果类中有__iter__方法  对象 >>>可迭代对象

               对象、__iter__()的返回值:迭代器

              for循环、迭代器 next

              for循环,可迭代对象,对象.__iter__(),迭代器 ,next.

              1、执行对象的类下 类中的__iner__方法,并获取其返回值

              2、循环上一步返回的对象

   

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __getitem__(self, item):    #特殊的方法支持索引  切片(slice类型)或者索引
        return item + 10

    def __setitem__(self, key, value):      #赋值  key 是100    value 是'qweasd'
        print(key,value)

    def __delitem__(self, key):
        print(key)

li = Foo('wangkuan',21)
r = li[8]#自动执行li对象的类中的方法 __getitem__方法,8当作参数传递给item
print(r)
li[100] = 'qweasd'
del li[999]
View Code

五、异常处理

    Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,她都会创建一个异常对象。如果你编写了处理处理该异常的代码,程序将自动运行,如果你未对异常进行处理,程序将停止,并显示一个

 traceback,其中包含有关异常的报告。

 异常格式:

try:
    #代码块   逻辑

except Exception as e:
    #上述代码块如果出错 ,自动执行当前块内容

  例子 让用户输入 数字  如果不是  自动执行  数字1 。

while True:


    try:
        inp = input('请输入序列:')
        i = int(inp)               #输入的不是整形  就异常处理




    except Exception as e:         #e是Exception 对象,对象中封装了错误信息;
                                   #输入的不是数字就执行数字 1
                                   # 执行当前块内容



        print(e)
        i = 1
        print(i)

  测试其他异常方法:    

     还有finally方法

#主要是为了测试  IndexError  ValueError  这两个处理异常的方法

try:
    li = [11,22,33]
    li[999]                     #索引不了这个位置 下面IndexError 执行


    # int('dfawfw')             #转换不了出这个错误 下面 ValueError执行
except IndexError as e:
       #如果是这种错误  执行这句          小弟搞 搞不了 老二搞
    print('IndexError',e)

except ValueError as e:
     #如果是这种错误  执行这句           老二搞不了  老大搞
    print('ValueError',e)

except Exception as e:
      所有错误都能用                      老大搞定
    print('Exception',e)

else:
    #上面没出错才执行下面代码         如果出错了 执行上面异常处理  然后执行finally
    print('else')


finally:                             #
 #最后不管对不对  都执行
    print('.....')

  

 主动抛出异常

 raise

try:
    raise Exception ('不过了!!!')     #主动触发异常

 #Exception ('不过了!!!')   Exception 加括号 相当于创建一个对象
 就会把找这个对象赋值给 e      e 就是这个错误的对象


except Exception as e:

    print(e)

  

 

 自定义异常

#自定义异常

class Abcd(Exception):
    def __init__(self,msg):
        self.message = msg

    def __str__(self):
        return self.message


try:
    raise Abcd('我错了。。。')
except Abcd as e:
    print(e) #e对象的__str__()方法,获取返回

  断言  assert

#断言
#assert  后面跟条件   条件、成立通过,不成立、报错。简单的一个判断,可捕获,一般不捕获。
#用于用户强制服从,不服从就报错。


print(123)
assert 1==1
#assert 1==2   不成立就报错
print(456)

  

 六、反射:

      通过字符串的形式操作对象中的成员

     getattr   去什么里面获取什么内容

     hasattr  是否有,去什么里面去检测有什么没有

     setattr   主动设置一个值

     delattr   删除

getattr   例子

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

obj = Foo('wangkuan',18)
#getattr() 去什么东西里面获取什么内容
#已经创建的对象 去obj获取name  name是字符串形式

k = getattr(obj,'age')
print(k)

#可以直接输入  因为input 接受的就是字符串
inp = input(">>>")
r = getattr(obj,inp)
print(r)

  也可以获取方法

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def shou(self):
        return "%s-%s" %(self.name,self.age)

obj = Foo('wangkuan',18)

abc = getattr(obj,'shou')          #abc 等于 shou了
print(abc)

r = abc()
print(r)

 

         hasattr  例子

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

obj = Foo('wangkuan',18)


r = hasattr(obj,'name')          检测 obj 里是否有name         检测 是否有

print(r)

  

setattr   例子

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

obj = Foo('wangkuan',18)


#obj.k1    报错了就   得在下面创建了
setattr(obj,"k1","v1")      #   主动设置一个值 k1 = v1
r = obj.k1
print(r)

  

delattr    例子

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age

obj = Foo('wangkuan',18)

delattr(obj,'name')   #把name删除

obj.name        #执行报错

  

 小的应用  模拟一个打开软件的功能    创建一个 s1   s2 让他们关联起来

s2

def f1():
    return '微信'
def f2():
    return '快手'
def f3():
    return '抖音'

s1

import s2

inp = input('相看啥??f1 f2 f3')
if hasattr(s2,inp):
    func = getattr(s2,inp)
    result = func()
    print(result)
else:
    print('输的啥呀  别看了   真是')

  

 

 七、单例 :就是单个实例,永远使用同一份实例(对象)

 

好处 内存里面对象只创建一次 永远用这一个 省内存

就打个比方 同一个网站有很多人访问 不能所有都去创建一个实例化 通过一个来实现

以后数据库 连接池的时候会用到 连接池只有一个 只创建一份 以后不管谁来 都用这一份

 

class Foo:
    __v = None        #单例  有值就还是一个储存地址
    @classmethod
    def get_instance(cls):
        if cls.__v:
            return cls.__v
        else:
            cls.__v = Foo()
            return cls.__v

obj1 = Foo.get_instance() 
#第一次执行 v等于空 执行slse  然后创建了一个对象 赋值给v   然后return回来了
# obj1 就等于你创建的那个对象
print(obj1)


obj2 = Foo.get_instance()#第二次执行 v以经有值了   执行if 还是之前那个对象 返回了
print(obj2)


obj3 = Foo.get_instance()   #第三次也是一样的
print(obj3)


#他们三个实例是一模一样的 通过类方法和静态字段伪造出  我以后想要这个对象时候  我只创建一次 以后拿着它在来就行了

  

 

posted @ 2018-08-29 12:03  取经之路  阅读(140)  评论(0)    收藏  举报