面向对象,绑定方法与异常处理(七)

2018-06-18 00:53:43来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

1.1 继承与派生

1.1.1 什么是继承

    是一种新建类的方式,新建的类称为子类,子类会遗传父类的属性,可以减少代码冗余
    在python中,子类(派生类)可以继承一个或者多个父类(基类,超类)
 
python中类的继承分为:单继承和多继承
class Parent1:    #定义父类

    pass

 

class Parent2(object): #定义父类

    pass

 

class Sub1(Parent1):  ##单继承,基类是Parent1,派生类是Sub1

    pass

 

class Sub2(Parent1,Parent2): #python支持多继承,用逗号分隔开多个继承的类

    pass

 

 
查看继承
print(Sub1.__bases__)   #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类

print(Sub2.__bases__)

提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。
print(Parent1.__bases__)

print(Parent2.__bases__)

 

 
在Python2中类分为两种:
1、经典类:指的就是没有继承object类的类,以及该类的子类
2、新式类:指的就是继承object类的类,以及该类的子类
在Python3中统一都为新式类
class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.sex = sex

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

 

class OldboyStudent(OldboyPeople):

    def learn(self):

        print('%s is learning' %self.name)

 

    def tell_info(self):

        print('我是学生:',end='')

        print('<名字:%s 年龄:%s 性别:%s>' % (self.name, self.age, self.sex))

 

class OldboyTeacher(OldboyPeople):

    def teach(self):

        print('%s is teaching' %self.name)

 

    def tell_info(self):

        print('我是老师:',end='')

        print('<名字:%s 年龄:%s 性别:%s>' % (self.name, self.age, self.sex))

 

stu1=OldboyStudent('牛榴弹',18,'male')

teacher1=OldboyTeacher('egon',18,'male')

 

print(stu1.__dict__)

print(stu1.school)

print(stu1.x)

 

stu1.tell_info()

teacher1.tell_info() 
 
 
属性查找
继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承
 
抽象即抽取类似或者说比较像的部分。
class Foo:

    def f1(self):

        print('Foo.f1')

 

    def f2(self): #self=obj

        print('Foo.f2')

        self.f1() #obj.f1()

 

class Bar(Foo):

    def f1(self):

        print('Bar.f1')

 

obj=Bar()

print(obj.__dict__)

obj.f2()

 

1.2 子类重用父类方法part1:

在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时

我们不可能从头开始写一个类B,这就用到了类的继承的概念。

通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.sex = sex

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

 

class OldboyStudent(OldboyPeople):

    def learn(self):

        print('%s is learning' %self.name)

 

    def tell_info(self):

        print('我是学生:',end='')

        # self.tell_info() #stu1.tell_info()

        OldboyPeople.tell_info(self)

 

stu1=OldboyStudent('牛榴弹',18,'male')

stu1.tell_info()

 

 

 

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.sex = sex

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

 

class OldboyStudent(OldboyPeople):

    def __init__(self,name,age,sex,course,stu_id):

        # self.name=name

        # self.age=age

        # self.sex=sex

        OldboyPeople.__init__(self,name,age,sex)

        self.course=course

        self.stu_id=stu_id

 

    def learn(self):

        print('%s is learning' %self.name)

 

    def tell_info(self):

        print('我是学生:',end='')

        # self.tell_info() #stu1.tell_info()

        OldboyPeople.tell_info(self)

 

stu1=OldboyStudent('牛榴弹',18,'male','Python',1)

stu1.tell_info()

 

 

 

1.3 组合

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.sex = sex

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

 

class OldboyStudent(OldboyPeople):

    def __init__(self,name,age,sex,course,stu_id,year,mon,day):

        OldboyPeople.__init__(self,name,age,sex)

        self.course=course

        self.stu_id=stu_id

 

        self.year=year

        self.mon=mon

        self.day=day

 

    def learn(self):

        print('%s is learning' %self.name)

 

    def tell_info(self):

        print('我是学生:',end='')

        # self.tell_info() #stu1.tell_info()

        OldboyPeople.tell_info(self)

 

    def tell_birth(self):

        print('出生日期是:<%s-%s-%s>' %(self.year,self.mon,self.day))

 

class OldboyTeacher(OldboyPeople):

    def __init__(self, name, age, sex, level,salary,year,mon,day):

        OldboyPeople.__init__(self, name, age, sex)

        self.level=level

        self.salary=salary

 

        self.year=year

        self.mon=mon

        self.day=day

 

    def tell_birth(self):

        print('出生日期是:<%s-%s-%s>' %(self.year,self.mon,self.day))

 

    def teach(self):

        print('%s is teaching' % self.name)

 

    def tell_info(self):

        print('我是老师:', end='')

        OldboyPeople.tell_info(self)

 

 

stu1=OldboyStudent('牛榴弹',18,'male','Python',1,1983,3,11)

teacher1=OldboyTeacher('啊狗',18,'female',10,4000,1990,2,17)

 

 

stu1.tell_birth()

teacher1.tell_birth()

 

组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同,

1.继承的方式

通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。

当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人

2.组合的方式

用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3...

 

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.sex = sex

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' % (self.name, self.age, self.sex))

 

 

class OldboyStudent(OldboyPeople):

    def __init__(self, name, age, sex, course, stu_id,):

        OldboyPeople.__init__(self, name, age, sex)

        self.course = course

        self.stu_id = stu_id

 

 

 

    def learn(self):

        print('%s is learning' % self.name)

 

    def tell_info(self):

        print('我是学生:', end='')

        # self.tell_info() #stu1.tell_info()

        OldboyPeople.tell_info(self)

 

class OldboyTeacher(OldboyPeople):

    def __init__(self, name, age, sex, level, salary):

        OldboyPeople.__init__(self, name, age, sex)

        self.level = level

        self.salary = salary

 

    def teach(self):

        print('%s is teaching' % self.name)

 

    def tell_info(self):

        print('我是老师:', end='')

        OldboyPeople.tell_info(self)

 

class Date:

    def __init__(self,year,mon,day):

        self.year = year

        self.mon = mon

        self.day = day

 

    def tell_birth(self):

        print('出生日期是:<%s-%s-%s>' % (self.year, self.mon, self.day))

 

stu1 = OldboyStudent('牛榴弹', 18, 'male', 'Python', 1,)

date_obj1=Date(1983, 3, 11)

stu1.birth=date_obj1

 

 

teacher1 = OldboyTeacher('啊狗', 18, 'female', 10, 4000)

date_obj2=Date( 1990, 2, 17)

teacher1.birth=date_obj2

 

 

# print(stu1.birth)

# print(teacher1.birth)

 

stu1.birth.tell_birth() #date_obj1.tell_birth()

teacher1.birth.tell_birth()

 

 

 

 

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex,date_obj):

        self.name = name

        self.age = age

        self.sex = sex

        self.birth = date_obj

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' % (self.name, self.age, self.sex))

 

class OldboyStudent(OldboyPeople):

    def __init__(self, name, age, sex, course, stu_id,date_obj):

        OldboyPeople.__init__(self, name, age, sex,date_obj)

        self.course = course

        self.stu_id = stu_id

 

 

    def learn(self):

        print('%s is learning' % self.name)

 

    def tell_info(self):

        print('我是学生:', end='')

        # self.tell_info() #stu1.tell_info()

        OldboyPeople.tell_info(self)

 

class OldboyTeacher(OldboyPeople):

    def __init__(self, name, age, sex, level, salary,date_obj):

        OldboyPeople.__init__(self, name, age, sex,date_obj)

        self.level = level

        self.salary = salary

 

    def teach(self):

        print('%s is teaching' % self.name)

 

    def tell_info(self):

        print('我是老师:', end='')

        OldboyPeople.tell_info(self)

 

class OldboySale(OldboyPeople):

    def __init__(self,name,age,sex,kpi,date_obj):

        OldboyPeople.__init__(self,name,age,sex,date_obj)

        self.kpi=kpi

 

    def tell_info(self):

        print('我是销售: ',end='')

        OldboyPeople.tell_info(self)

 

class Date:

    def __init__(self,year,mon,day):

        self.year = year

        self.mon = mon

        self.day = day

 

    def tell_birth(self):

        print('出生日期是:<%s-%s-%s>' % (self.year, self.mon, self.day))

 

date_obj1=Date(1983, 3, 11)

sale1=OldboySale('歪歪',38,'male',7.3,date_obj1)

# sale1.birth=date_obj1

# sale1.tell_info()

 

sale1.birth.tell_birth()

 

 

 

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex,date_obj):

        self.name = name

        self.age = age

        self.sex = sex

        self.birth = date_obj

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' % (self.name, self.age, self.sex))

 

class OldboyStudent(OldboyPeople):

    def __init__(self, name, age, sex, stu_id,date_obj):

        OldboyPeople.__init__(self, name, age, sex,date_obj)

        self.courses=[]

        self.stu_id = stu_id

 

 

    def learn(self):

        print('%s is learning' % self.name)

 

    def tell_info(self):

        print('我是学生:', end='')

        # self.tell_info() #stu1.tell_info()

        OldboyPeople.tell_info(self)

 

class OldboyTeacher(OldboyPeople):

    def __init__(self, name, age, sex, level, salary,date_obj):

        OldboyPeople.__init__(self, name, age, sex,date_obj)

        self.level = level

        self.salary = salary

        self.courses=[]

 

    def teach(self):

        print('%s is teaching' % self.name)

 

    def tell_info(self):

        print('我是老师:', end='')

        OldboyPeople.tell_info(self)

 

class OldboySale(OldboyPeople):

    def __init__(self,name,age,sex,kpi,date_obj):

        OldboyPeople.__init__(self,name,age,sex,date_obj)

        self.kpi=kpi

 

    def tell_info(self):

        print('我是销售: ',end='')

        OldboyPeople.tell_info(self)

 

class Date:

    def __init__(self,year,mon,day):

        self.year = year

        self.mon = mon

        self.day = day

 

    def tell_birth(self):

        print('出生日期是:<%s-%s-%s>' % (self.year, self.mon, self.day))

 

class Course:

    def __init__(self,name,price,period):

        self.name=name

        self.price=price

        self.period=period

 

    def tell_info(self):

        print('课程详细信息:<%s,%s,%s>' %(self.name,self.price,self.period))

 

Python=Course('python自动化养猪',3000,'3mon')

Linux=Course('大数据分析-linux',3000,'3mon')

date_obj=Date(1993,3,13)

 

teacher1=OldboyTeacher('egon',18,'male',100,3000,date_obj)

teacher1.courses.append(Python)

teacher1.courses.append(Linux)

 

# print(teacher1.courses)

for course in teacher1.courses:

    course.tell_info()

 

 

stu1=OldboyStudent('xxxx',28,'female',1,date_obj)

# print(stu1.courses)

 

stu1.courses.append(Python)

stu1.courses.append(Linux)

 

print(stu1.courses)

 

 

 

1.4 抽象类

1.4.1 什么是抽象类

与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

为什么要有抽象类

    如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

  比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。

    从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

  从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案

 

import abc

 

class Animal(metaclass=abc.ABCMeta):

    @abc.abstractmethod

    def eat(self):

        pass

 

    @abc.abstractmethod

    def run(self):

        pass

 

 

class People(Animal):

    def eat(self):

        pass

    def run(self):

        pass

 

class Pig(Animal):

    def eat(self):

        pass

    def run(self):

        pass

 

peo1=People()

pig1=Pig()

 

 

1.4.2 抽象类与接口

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计

import abc

 

class File(metaclass=abc.ABCMeta):

    @abc.abstractmethod

    def read(self):

        pass

 

    @abc.abstractmethod

    def write(self):

        pass

 

class Disk(File):

    def read(self):

        print('disk read')

 

    def write(self):

        print('disk write')

 

 

class Process(File):

    def read(self):

        print('Process read')

 

    def write(self):

        print('Process write')

 

d=Disk()

p=Process()

 

d.read()

d.write()

 

p.read()

p.write()

 

 

 

1.5 继承的实现原理

继承顺序

在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如A(B,C,D)

如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性

如果继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先

 

 

图1-1  

 

 

图1-2  

class A(object):

    # def test(self):

    #     print('from A')

    pass

 

class B(A):

    # def test(self):

    #     print('from B')

    pass

 

class C(A):

    # def test(self):

    #     print('from C')

    pass

class D(B):

    # def test(self):

    #     print('from D')

    pass

 

class E(C):

    # def test(self):

    #     print('from E')

    pass

class F(D,E):

    # def test(self):

    #     print('from F')

    pass

 

f1=F()

print(F.mro())

# f1.test()

 

 

 

 

1.6 子类重用父类的方法part2

1.6.1 方法一:指名道姓,即父类名.父类方法()

class OldboyPeople:

    school = 'Oldboy'

 

    def __init__(self, name, age, sex):

        self.name = name

        self.age = age

        self.sex = sex

 

    def tell_info(self):

        print('<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex))

 

class OldboyStudent(OldboyPeople):

    def __init__(self,name,age,sex,course):

        # OldboyPeople.__init__(self,name,age,sex)

        super(OldboyStudent,self).__init__(name,age,sex)

        self.course=course

 

    def tell_info(self):

        print('我是学生: ',end='')

        # OldboyPeople.tell_info(self)

        super(OldboyStudent,self).tell_info()

 

 

stu1=OldboyStudent('egon',18,'male','python')

 

# print(stu1.name,stu1.age,stu1.sex,stu1.course)

stu1.tell_info()

 

1.6.2 方法二:super()

class Foo:

    def f2(self):

        print('====?>')

 

    def f1(self):

        print('Foo.f1')

        # super().f2()

        Foo.f2(123)

class Bar:

    def f2(self):

        print('Bar f2')

 

class Sub(Foo,Bar):

    pass

 

s=Sub()

# print(Sub.mro())

# [<class '__main__.Sub'>,

# <class '__main__.Foo'>,

# <class '__main__.Bar'>,

#  <class 'object'>]

 

s.f1()

 

强调:二者使用哪一种都可以,但最好不要混合使用

即使没有直接继承关系,super仍然会按照mro继续往后查找

1.6.3 指名道姓与super()的区别

当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)

1.7 多态与多态性

1.7.1 多态:同一种事物的多种形态

import abc

 

class Animal(metaclass=abc.ABCMeta):

    @abc.abstractmethod

    def speak(self):

        pass

 

class Pig(Animal):

    def speak(self):

        print('哼哼')

 

class Dog(Animal):

    def speak(self):

        print('汪汪')

 

class People(Animal):

    def speak(self):

        print('say hello')

 

 

 

people1=People()

dog1=Dog()

pig1=Pig()

 

 

1.7.2 多态性:指的是在不考虑对象具体类型的情况下,直接使用对象(对象的方法)

people1.speak()

dog1.speak()

pig1.speak()

 

def talk(obj):

    obj.speak()

 

talk(people1) #people1.speak()

talk(dog1)

talk(pig1)

 

 

list,str,tuple

l=list([1,2,3])

s=str('hello')

t=tuple((1,'a',4,'b','c'))

 

l.__len__()

s.__len__()

t.__len__()

 

print(len(l))

print(len(s))

print(len(t))

 

 

多态性是指在不考虑实例类型的情况下使用实例

多态:同一种事物的多种形态

1.7.3 多态性分为静态多态性和动态多态性

  静态多态性:如任何类型都可以用运算符+进行运算

  动态多态性:

import abc

 

class Pig:

    def speak(self):

        print('哼哼')

 

class Dog:

    def speak(self):

        print('汪汪')

 

class People:

    def speak(self):

        print('say hello')

 

class Radio:

    def speak(self):

        print('radio speak')

 

 

people1=People()

dog1=Dog()

pig1=Pig()

 

 

1.7.4 为什么要用多态性

其实大家从上面多态性的例子可以看出,我们并没有增加什么新的知识,也就是说python本身就是支持多态性的,这么做的好处是什么呢?

1.增加了程序的灵活性

  以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)

2.增加了程序额可扩展性

  通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用  

 

import abc

 

class Disk:

    def read(self):

        print('disk read')

 

    def write(self):

        print('disk write')

 

 

class Process:

    def read(self):

        print('Process read')

 

    def write(self):

        print('Process write')

  

 

1.8 封装之如何隐藏

1.8.1 封装:

1、__开头的属性只是一种语法意义上的变形,并不会真的限制外部的访问

2、这种变形只在类定义阶段发送一次,类定义之后再新增的__开头的属性不会变形

3、这种隐藏只对外不对内,因为类内部定义的属性在类定义阶段统一发生变形

先看如何隐藏

在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

class Foo:

    __N=1 #_Foo__N=1

    def __init__(self,x,y):

        self.x=x

        self.__y=y #self._Foo__y=y

 

    def __f1(self): #_Foo__f1

        print('f1')

 

    def f2(self):

        print(self.__N,self.__y) #print(self._Foo__N,self._Foo__y)

 

print(Foo.__N)

print(Foo.__f1)

print(Foo.__dict__)

print(Foo._Foo__N)

print(Foo._Foo__f1)

 

obj=Foo(1,2)

print(obj.__dict__)

print(obj._Foo__y)

 

Foo.__M=2

print(Foo.__dict__)

print(Foo.__M)

 

obj=Foo(1,2)

print(obj.__dict__)

obj.__z=3

print(obj.__dict__)

print(obj.__z)

 

obj=Foo(1,2)

obj.f2()

print(obj.__N)

 

这种变形需要注意的问题是:

1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形,主要用来限制外部的直接访问。

2.变形的过程只在类的定义时发生一次,在定义后的赋值操作,不会变形

3.继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

class Foo:

    def __f1(self): #_Foo__f1

        print('Foo.f1')

 

    def f2(self):

        print('Foo.f2')

        self.__f1() #b._Foo__f1()

 

class Bar(Foo):

    def __f1(self): #_Bar__f1

        print('Bar.f1')

 

 

b=Bar()

b.f2()

 

 

 

1.9 封装之真正意义

封装数据属性的目的:外部无法直接访问数据属性,类内部开放接口,然后可以在接口内严格控制对属性的增删改查操作

class People:

    def __init__(self,name,age):

        # self.__name=name

        # self.__age=age

        self.set_info(name,age)

 

    def tell_info(self):

        print("姓名:<%s> 年龄:<%s>" %(self.__name,self.__age))

 

    def set_info(self,name,age):

        if type(name) is not str:

            raise TypeError('name must be str')

        if type(age) is not int:

            raise TypeError('age must be int')

 

        self.__name=name

        self.__age=age

 

p=People('egon',18)

 

# print(p.__name,p.__age)

# p.tell_info()

 

# p.set_info('EGON',20)

p.set_info(3537,20)

p.tell_info()

 

 

封装方法的目的是:隔离复杂度

 

class ATM:

    def __card(self):

        print('插卡')

    def __auth(self):

        print('用户认证')

    def __input(self):

        print('输入取款金额')

    def __print_bill(self):

        print('打印账单')

    def __take_money(self):

        print('取款')

 

    def withdraw(self):

        self.__card()

        self.__auth()

        self.__input()

        self.__print_bill()

        self.__take_money()

 

 

 

1.10 封装之property

1.10.1 什么是特性property

 

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:

过轻:低于18.5

正常:18.5-23.9

过重:24-27

肥胖:28-32

非常肥胖, 高于32

  体质指数(BMI)=体重(kg)÷身高^2(m)

EX:70kg÷(1.75×1.75)=22.86

 

class People:

    def __init__(self,name,age,height,weight):

        self.name=name

        self.age=age

        self.height=height

        self.weight=weight

 

    @property

    def bmi(self):

        return self.weight / (self.height ** 2)

 

egon=People('egon',18,1.80,75)

egon.height=1.82

# print(egon.bmi())

 

print(egon.bmi)

 

 

 

1.10.2 为什么要用property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

 

class People:

    def __init__(self,name,):

        self.__name=name

 

    @property

    def name(self):

        return self.__name

 

    @name.setter

    def name(self,obj):

        if type(obj) is not str:

            raise TypeError('name must be str')

        self.__name=obj

 

    @name.deleter

    def name(self):

        # del self.__name

        raise PermissionError('不让删')

 

egon=People('egon')

 

# print(egon.name)

 

# egon.name='EGON'

# egon.name=35357

# print(egon.name)

 

del egon.name

 

# print(egon.name)

 

 

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

 

1.11 绑定方法与非绑定方法

一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):

    1. 绑定到类的方法:用classmethod装饰器装饰的方法。

                为类量身定制

                类.boud_method(),自动将类当作第一个参数传入

              (其实对象也可调用,但仍将类当作第一个参数传入)

    2. 绑定到对象的方法:没有被任何装饰器装饰的方法。

               为对象量身定制

               对象.boud_method(),自动将对象当作第一个参数传入

             (属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

二:非绑定方法:用staticmethod装饰器装饰的方法

        1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已

    注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

 

1.11.1 绑定方法

绑定给对象的方法(略)

绑定给类的方法(classmethod)

classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数classmethod来把类中的函数定义成类方法

 

import settings

import hashlib

import time

 

class MySQL:

    def __init__(self,host,port):

        self.host=host

        self.port=port

 

    def func(self):

        print('%s 说:你好啊我的天' %self.name)

 

    @classmethod

    def from_conf(cls):

        return cls(settings.HOST,settings.PORT)

 

    @staticmethod

    def create_id(n):

        m=hashlib.md5()

        m.update(str(time.clock()+n).encode('utf-8'))

        return m.hexdigest()

# conn=MySQL('127.0.0.1',3306)

 
#绑定方法:绑定给谁就应该由谁来调用,谁来调用就会把谁当做第一个参数自动传入
 

1.11.2 非绑定方法

在类内部用staticmethod装饰的函数即非绑定方法,就是普通函数
statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果
conn=MySQL.from_conf()

# print(conn.host,conn.port)

 

 

print(MySQL.create_id(1))

print(conn.create_id(2))

 

 

 

1.12 内置函数补充

l=list([])

 

print(type(l) is list)

print(isinstance(l,list))

 

class Foo:

    pass

 

class Bar(Foo):

    pass

 

print(issubclass(Bar,Foo))

 

 

 

1.13 反射

1.13.1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

class Foo:

    def __init__(self,name):

        self.name=name

 

    def f1(self):

        print('===>f1')

 

obj=Foo('egon')

obj.name #obj.__dict__['name']

 

1.13.2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

hasattr

print(hasattr(obj,'name')) #obj.name

print(hasattr(obj,'f1'))#obj.f1

 

getattr

if hasattr(obj,'f1'):

    f=getattr(obj,'f1') #f=obj.f1

    f()

print(getattr(obj,'xxx',None))

 

 

setattr

obj.x=1

setattr(obj,'x',1)

print(obj.__dict__)

 

 

delattr

del obj.name

delattr(obj,'name')

print(obj.__dict__)

 

导入其他模块,利用反射查找该模块是否存在某个方法

class FtpClient:

    def __init__(self,host,port):

        self.host=host

        self.port=port

        self.conn='xxx'

 

    def interactie(self):

        while True:

            cmd=input('>>: ').strip()

            if not cmd:continue

            cmd_l=cmd.split()

            print(cmd_l)

            if hasattr(self,cmd_l[0]):

                func=getattr(self,cmd_l[0])

                func(cmd_l)

 

    def get(self,cmd_l):

        print('geting...',cmd_l)

 

    def put(self,cmd_l):

        print('putting....',cmd_l)

 

client=FtpClient('1.1.1.1',23)

client.interactie()

 

 

 

1.14 类的内置方法

__str__

l=list([1,2,3,4])

print(l)

 

class People:

    def __init__(self,name,age):

        self.name=name

        self.age=age
    def __str__(self):

        return '<name:%s age:%s>' %(self.name,self.age)

 

egon=People('egon',18)

print(egon) #print(egon.__str__())

 

 

 

注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__

__del__

f=open('a.txt','w',encoding='utf-8')

f.read()

f.close()

 

 

 

class Foo:

    def __del__(self):

        print('del---->')

 

obj=Foo()

del obj

# print('主')

 

 

setting.py

HOST='10.10.10.9'

PORT=3306

 

 

class Mysql:

    def __init__(self,host,port):

        self.host=host

        self.port=port

        self.conn=Connect(host,port)

 

    def __del__(self):

        self.conn.close()

 

m=Mysql('1.1.1.1',3306)

m.conn.execute('select * from db.user;')

 

 

1.15 异常处理

1.15.1 什么是异常

异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下

而错误分成两种

1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) 

2.逻辑错误

# x=

 

raise TypeError('xxxx')

 

为了保证程序的健壮性与容错性,即在遇到错误时程序不会崩溃,我们需要对异常进行处理,

如果错误发生的条件是可预知的,我们需要用if进行处理:在错误发生之前进行预防

#基本语法为

try:

    被检测的代码块

except 异常类型:

    try中一旦检测到异常,就执行这个位置的逻辑

#举例

try:

    f=open('a.txt')

    g=(line.strip() for line in f)

    print(next(g))

    print(next(g))

    print(next(g))

    print(next(g))

    print(next(g))

except StopIteration:

    f.close()

 

 

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:window下spyder的快捷键

下一篇:Python配置环境变量