前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python Day7

Python Day7

作者头像
py3study
发布2020-01-13 15:58:51
4060
发布2020-01-13 15:58:51
举报
文章被收录于专栏:python3

继承与派生

什么是继承

是一种新建类的方式,新建的类称为子类,子类会遗传父亲的属性,可以减少代码冗余 在python当中,子类(派生类)可以继承一个或多个父类(基类,超类)

在python3中定义类时不写父类默认会继承object 在python2中需要写object 所以,为了兼容,在定义类时可以写上默认的object

代码语言:javascript
复制
class Parent1(object): #python3是不需要写上(object)的,但其实是有的
    pass

class Parent2:
    pass

class Sub1(Parent1):
    pass

class Sub2(Parent1,Parent2): #继承多个父类
    pass
代码语言:javascript
复制
print(Sub1.__bases__) #查看有哪些父类
print(Sub2.__bases__)

经典类与新式类

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

继承可以实现代码重用

派生

当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

注意: 在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值

继承、派生示例

代码语言:javascript
复制
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('dzm',18,'male')
teacher1=OldboyTeacher('egon',18,'male')

teacher1.tell_info() #子类中有tell_info则使用子类中的tell_info

属性查找

先在对象自己的名称空间查找,再在所属的子类名称空间查找,再在子类的父类的名称空间中查找

代码语言:javascript
复制
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()

结果:

代码语言:javascript
复制
{}
Foo.f2
Bar.f1

子类重用父类的功能之直接指定

此时就与调用普通函数无异了,因此即便是self参数也要为其传值

示例2:

代码语言:javascript
复制
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')
代码语言:javascript
复制
stu1.tell_info()

结果:
我是学生:<名字:牛榴弹 年龄:18 性别:male>

示例2:

代码语言:javascript
复制
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

代码语言:javascript
复制
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))

学生有生日的属性,老师也有生日的属性,但学生和老师都不是生日,因此不符合什么是什么的继承关系 但学生和老师都有生日这个属性,可以理解为什么有什么的关系 这里使用组合,专门定义一个日期类,组合也可以减少代码重用

代码语言:javascript
复制
stu1 = OldboyStudent('牛榴弹', 18, 'male', 'Python', 1,) #实例化一个学生对象
date_obj1=Date(1983, 3, 11)  #实例化一个日期对象
stu1.birth=date_obj1 #给stu1这个对象添加一个名为birth的属性,把上面的日期实例赋值给它

看一个赋值后的stu1.birth是什么

代码语言:javascript
复制
print(stu1.birth)
结果:
<__main__.Date object at 0x000001CEB43A2240>

名为birth的属性实际指向了date_obj1这个对象,也就是指向了它后面的Date这个类 这样就等于把两个类间接的组合到了一起

既然已经把date_obj1这个对象赋值给了stu1.birth,那我们可以借此调用Date类里面的函数 stu1.birth.tell_birth() #等于date_obj1.tell_birth() 结果: 出生日期是:<1983-3-11>

组合示例2

代码语言:javascript
复制
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))
代码语言:javascript
复制
#实例化两个课程
Python=Course('python自动化养猪',3000,'3mon')
Linux=Course('大数据分析-linux',3000,'3mon')
 #实例化一个日期对象
date_obj=Date(1993,3,13)  

#初始化时直接设定生日属性,这里与示例1不同,但原理上一样使用组合
# 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()
代码语言:javascript
复制
stu1=OldboyStudent('xxxx',28,'female',1,date_obj)
# print(stu1.courses)

stu1.courses.append(Python)
stu1.courses.append(Linux)

print(stu1.courses)
结果:
[<__main__.Course object at 0x0000024AD3683518>, <__main__.Course object at 0x0000024AD3683550>]
代码语言:javascript
复制
for course in stu1.courses:  #使用for循环可以直接取出课程
    course.tell_info()
结果:
课程详细信息:<python自动化养猪,3000,3mon>
课程详细信息:<大数据分析-linux,3000,3mon>

抽象类

从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。 抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 这里模拟linux上一切皆文件的概念

import abc

定义一个父类,定义读写两个函数

代码语言:javascript
复制
class File(metaclass=abc.ABCMeta): #指定一个类的原类,metaclass是类似创建类的模板
    @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')

实例出两个对象

代码语言:javascript
复制
d=Disk()
p=Process()

在使用时无需关心到底是什么,使用方法都是一样的 这样大家都是被归一化了,也就是一切皆文件的思想

代码语言:javascript
复制
d.read()
d.write()

p.read()
p.write()

继承实现的原理

深度优先与广度优先

python如何实现的继承

对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。

Python3提供了一个.mro方法,可以以列表形式显示出查找顺序

代码语言:javascript
复制
...........省略...........
f1=F()
print(F.mro())
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止

子类重用父类的功能之super

理解了继承原理,就可以看一下另一种子类重用父类功能的方法super() 当你使用super()函数时,Python会在MRO列表上继续搜索下一个类 两种子类重用父类功能的方法最好不要混用

super示例1

代码语言:javascript
复制
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()

示例2

代码语言:javascript
复制
class Foo:
    def f2(self):
        print('====?>')

    def f1(self):
        print('Foo.f1')
        super().f2()

class Bar:
    def f2(self):
        print('Bar f2')

class Sub(Foo,Bar):
    pass
代码语言:javascript
复制
s=Sub()
# print(Sub.mro())
# [<class '__main__.Sub'>,
# <class '__main__.Foo'>,
# <class '__main__.Bar'>,
#  <class 'object'>]

s.f1()

结果:

代码语言:javascript
复制
Foo.f1
Bar f2  #结果反映出调用是从MRO列表当前的位置往后找,而不是找它自己的

注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表

多态与多态性

多态

多态指的是一类事物有多种形态,比如 动物有多种形态:人,狗,猪

代码语言:javascript
复制
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
    @abc.abstractmethod
    def talk(self):
        pass

class People(Animal): #动物的形态之一:人
    def talk(self):
        print('say hello')

class Dog(Animal): #动物的形态之二:狗
    def talk(self):
        print('say wangwang')

class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print('say aoao')

多态性

什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)

多态性是指在不考虑实例类型的情况下使用实例,多态性分为静态多态性和动态多态性

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

动态多态性:如下

代码语言:javascript
复制
peo=People()
dog=Dog()
pig=Pig()

peo、dog、pig都是动物,只要是动物肯定有talk方法 于是我们可以不用考虑它们三者的具体是什么类型,而直接使用

代码语言:javascript
复制
peo.talk()
dog.talk()
pig.talk()

更进一步,我们可以定义一个统一的接口来使用

代码语言:javascript
复制
def func(obj):
    obj.talk()

func(peo)
func(pig)

结果:

代码语言:javascript
复制
say hello
say aoao

为什么要用多态性(多态性的好处)

1.增加了程序的灵活性

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

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

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

鸭子类型

Python崇尚鸭子类型

“鸭子类型”的语言是这么推断的:一只鸟走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,那它就可以被当做鸭子。 也就是说,它不关注对象的类型,而是关注对象具有的行为(方法)。

举例: 序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系

str,list,tuple都是序列类型

代码语言:javascript
复制
s=str('hello')
l=list([1,2,3])
t=tuple((4,5,6))

我们可以在不考虑三者类型的前提下使用s,l,t

代码语言:javascript
复制
s.__len__()
l.__len__()
t.__len__()

len(s)
len(l)
len(t)

封装

如何隐藏

1、开头的属性只是一种语法意义上的变形,并不会真的限制外部的访问 2、这种变形只在类定义阶段发送一次,类定义之后再新增的开头的属性不会变形 3、这种隐藏只对外不对内,因为类内部定义的属性在类定义阶段统一发生变形

代码语言:javascript
复制
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)

在知道规则的情况下可以找到所需内容,可见并不是真正意义的隐藏

代码语言:javascript
复制
print(Foo._Foo__N)
print(Foo._Foo__f1)

结果:

代码语言:javascript
复制
1
<function Foo.__f1 at 0x000001FAB8468AE8>
代码语言:javascript
复制
obj=Foo(1,2)
print(obj.__dict__)
print(obj._Foo__y)

结果:

代码语言:javascript
复制
{'x': 1, '_Foo__y': 2}
2
代码语言:javascript
复制
obj=Foo(1,2)
obj.f2()
结果:
1 2

封装的真正意义

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

代码语言:javascript
复制
class People:
    def __init__(self,name,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('dzm',18)
p.tell_info()

修改

代码语言:javascript
复制
p.set_info('DZM',20)
p.tell_info()

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

代码语言:javascript
复制
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()

d=ATM()
d.withdraw()

取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱 对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做 隔离了复杂度,同时也提升了安全性

封装之property

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

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

代码语言:javascript
复制
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)
代码语言:javascript
复制
egon=People('egon',18,1.80,75)
egon.height=1.82
print(egon.bmi())

此时获取bmi要调取类中的函数,但bmi也应该是人的属性之一,像查看属性(egon.bmi)那样查看岂不更好?使用@property实现了这一点 print(egon.bmi)

代码语言:javascript
复制
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('不让删')

@name.setter和@name.deleter都是固定用法

代码语言:javascript
复制
egon=People('egon')
print(egon.name)

修改

代码语言:javascript
复制
egon.name='EGON' #使用了@name.setter就可以像修改属性那样操作了
egon.name=35357 #因为做了判断,所以此时会返回异常'name must be str'
print(egon.name)

del egon.name #使用了@name.deleter就可以像删除属性那样操作了

真正的封装是,经过深入的思考,做出良好的抽象,给出“完整且最小”的接口,并使得内部细节可以对外透明

(注意:对外透明的意思是,外部调用者可以顺利的得到自己想要的任何功能,完全意识不到内部细节的存在)

绑定方法与非绑定方法

这里以从文件传参来举例

代码语言:javascript
复制
import settings #从文件读取HOST和PORT
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  #当需要传进来的是类时,使用@classmethod
    def from_conf(cls): #此时cls等于MySQL
        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.from_conf()

当函数体代码不需要类传进来也不需要对象自动传进来时,这种函数就定义成非绑定方法 此时我们来看看结果

代码语言:javascript
复制
print(MySQL.create_id)
print(conn.create_id)

结果:

代码语言:javascript
复制
<function MySQL.create_id at 0x0000013A42048E18>
<function MySQL.create_id at 0x0000013A42048E18>

使用@staticmethod后无论是对象调用还是类调用都显示为一个函数而已

使用非绑定方法不意味着不需要传参

代码语言:javascript
复制
print(MySQL.create_id(1))
print(conn.create_id(2))

结果:

代码语言:javascript
复制
85a3525bf7884cad61c0c2fea69f08ed
38dea5a04f7a37b41f69eb5c7b396787

内置函数补充

isinstance 判断类型

判断类型可以不用type了

代码语言:javascript
复制
l=list([])

print(type(l) is list)
print(isinstance(l,list))

判断l是不是list的实例 结果: True

issubclass

判断一个类是不是另一个类的子类

代码语言:javascript
复制
class Foo:
    pass

class Bar(Foo):
    pass

print(issubclass(Bar,Foo)) 检查Bar类是否是 Foo类的派生类(子类) 结果: True

面向对象进阶

反射

能够通过字符串映射到属性身上

代码语言:javascript
复制
class Foo:
    def __init__(self,name):
        self.name=name

    def f1(self):
        print('===>f1')

obj=Foo('egon')
代码语言:javascript
复制
正常调用属性
# obj.name #obj.__dict__['name']

hasattr 判断object中有没有一个name字符串对应的方法或属性

代码语言:javascript
复制
print(hasattr(obj,'name')) #等同于obj.name
print(hasattr(obj,'f1')) #等同于obj.f1

有就返回True

getattr

代码语言:javascript
复制
if hasattr(obj,'f1'): 判断obj下与没有f1这个属性或发放
    f=getattr(obj,'f1') #f=obj.f1 有则拿到它,通过字符串的方式
    f() #拿到一个内存地址,加括号直接执行
print(getattr(obj,'xxx',None)) #None是默认返回值,如果你不做判断直接获取的话,若没有则会报错,此时加个None,会返回None

setattr #设置(添加、修改)

代码语言:javascript
复制
setattr(obj,'x',1) #等同于obj.x=1
print(obj.__dict__) #检查一下是否有了

delattr #删除

代码语言:javascript
复制
del obj.name
delattr(obj,'name')
print(obj.__dict__)

使用示例1:

代码语言:javascript
复制
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()

类的内置方法

str

内置方法是在某种行为发生的时候默认触发

代码语言:javascript
复制
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)
        # 在打印对象的时候不要打印内存地址,希望打印有用的东西
代码语言:javascript
复制
egon=People('egon',18)
print(egon) #print(egon.__str__())

结果:

代码语言:javascript
复制
<name:egon age:18>

这个str函数默认就有 在打印时触发 默认打印的就是内存地址

del

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

代码语言:javascript
复制
f=open('a.txt','w',encoding='utf-8')
f.read()
f.close()

class Foo:
    def __del__(self):
        print('del---->')
代码语言:javascript
复制
obj=Foo()
del obj
print('主')

结果:

代码语言:javascript
复制
del---->
主
代码语言:javascript
复制
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;')

先回收操作系统资源再回收m这个对象

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 继承与派生
    • 什么是继承
      • 经典类与新式类
        • 派生
          • 继承、派生示例
            • 属性查找
            • 子类重用父类的功能之直接指定
            • 组合
              • 组合示例1
                • 组合示例2
                • 抽象类
                • 继承实现的原理
                  • 深度优先与广度优先
                    • python如何实现的继承
                    • 子类重用父类的功能之super
                    • 多态与多态性
                      • 多态
                        • 多态性
                          • 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)
                          • 为什么要用多态性(多态性的好处)
                        • 鸭子类型
                        • 封装
                          • 如何隐藏
                            • 封装的真正意义
                              • 封装之property
                              • 绑定方法与非绑定方法
                              • 内置函数补充
                                • isinstance 判断类型
                                  • issubclass
                                  • 面向对象进阶
                                    • 反射
                                      • 类的内置方法
                                        • str
                                        • del
                                    相关产品与服务
                                    云数据库 MySQL
                                    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档