多态与多态性

一,多态

1,多态指的是一类事物有多种形态(python里面原生多态)

1.1动物有多种形态:人,狗,猪

  1. import abc
  2. class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
  3. @abc.abstractmethod
  4. def talk(self):
  5. pass
  6.  
  7. class People(Animal): #动物的形态之一:人
  8. def talk(self):
  9. print('say hello')
  10.  
  11. class Dog(Animal): #动物的形态之二:狗
  12. def talk(self):
  13. print('say wangwang')
  14.  
  15. class Pig(Animal): #动物的形态之三:猪
  16. def talk(self):
  17. print('say aoao')

1.2 文件有多种形态:文本文件,可执行文件

  1. import abc
  2. class File(metaclass=abc.ABCMeta): #同一类事物:文件
  3. @abc.abstractmethod
  4. def click(self):
  5. pass
  6.  
  7. class Text(File): #文件的形态之一:文本文件
  8. def click(self):
  9. print('open file')
  10.  
  11. class ExeFile(File): #文件的形态之二:可执行文件
  12. def click(self):
  13. print('execute file')

  

二,多态性

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

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

  在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息(!!!obj.func():是调用了
obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现。

  比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同

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

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

  动态多态性:如下

  1. peo=People()
  2. dog=Dog()
  3. pig=Pig()
  4.  
  5. #peo、dog、pig都是动物,只要是动物肯定有talk方法
  6. #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
  7. peo.talk()
  8. dog.talk()
  9. pig.talk()
  10.  
  11. #更进一步,我们可以定义一个统一的接口来使用
  12. def func(obj):
  13. obj.talk()

  

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

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

1.增加了程序的灵活性

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

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

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

  1. >>> class Cat(Animal): #属于动物的另外一种形态:猫
  2. ... def talk(self):
  3. ... print('say miao')
  4. ...
  5. >>> def func(animal): #对于使用者来说,自己的代码根本无需改动
  6. ... animal.talk()
  7. ...
  8. >>> cat1=Cat() #实例出一只猫
  9. >>> func(cat1) #甚至连调用方式也无需改变,就能调用猫的talk功能
  10. say miao
  11.  
  12. '''
  13. 这样我们新增了一个形态Cat,由Cat类产生的实例cat1,使用者可以在完全不需要修改自己代码的情况下。
    使用和人、狗、猪一样的方式调用cat1的talk方法,即func(cat1)
  14. '''

  

三,鸭子类型

逗比时刻:

  Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’

  python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象

  也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。

  例1:利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法

  1. #二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
  2. class TxtFile:
  3. def read(self):
  4. pass
  5.  
  6. def write(self):
  7. pass
  8.  
  9. class DiskFile:
  10. def read(self):
  11. pass
  12. def write(self):
  13. pass

  例2:其实大家一直在享受着多态性带来的好处,比如Python的序列类型有多种形态:字符串,列表,元组,多态性体现如下

  1. #str,list,tuple都是序列类型
  2. s=str('hello')
  3. l=list([1,2,3])
  4. t=tuple((4,5,6))
  5.  
  6. #我们可以在不考虑三者类型的前提下使用s,l,t
  7. s.__len__()
  8. l.__len__()
  9. t.__len__()
  10.  
  11. len(s)
  12. len(l)
  13. len(t)

  

绑定方法与非绑定方法

一:类中定义的函数分为两大类

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

  绑定方法分为绑定到类的方法和绑定到对象的方法,具体如下:

  1. 1. 绑定到类的方法:用classmethod装饰器装饰的方法。
  2.                 为类量身定制
  3.                 类.boud_method(),自动将类当作第一个参数传入
  4.               (其实对象也可调用,但仍将类当作第一个参数传入)
  5.  
  6. 2. 绑定到对象的方法:没有被任何装饰器装饰的方法。
  7.                为对象量身定制
  8.                对象.boud_method(),自动将对象当作第一个参数传入
  9.              (属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

  

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

  1. 1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已
  2.     注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器
  3. 装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而
  4. staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

  

3:对于绑定方法和非绑定方法举个例子

  1. 在类内部定义的函数,分为两大类:
  2. 一:绑定对象:绑定给谁就由谁来调用,谁来调用就会把调用者当作第一个参数自动传入
  3. 绑定到对象的方法:在类内定义的没有被任何装饰器修饰的
  4. class Foo():
  5. def __init__(self,name):
  6. self.name = name
  7.  
  8. def tell(self):
  9. print('名字是%s'%self.name)
  10.  
  11. f = Foo('james')
  12. print(f.tell)
  13. # <bound method Foo.tell of <__main__.Foo object at 0x0000021B7AB3C9E8>>
  14. 绑定到类的方法:在类内定义的被装饰器classmethod修饰的方法
  15. # def 定义的两个都是绑定到对象的方法
  16. class Foo():
  17. def __init__(self,name):
  18. self.name = name
  19. @classmethod
  20. def func(cls): #cls = Foo
  21. print(cls)
  22. print(Foo.func)
  23. # <bound method Foo.func of <class '__main__.Foo'>>
  24.  
  25. 二:非绑定方法:没有自动传值这一说法,简单说就是一个普通方法
  26. 非绑定方法:不与类或者对象绑定,谁都可以调用
  27. class Foo():
  28. def __init__(self,name):
  29. self.name = name
  30. @classmethod
  31. def func(cls): #cls = Foo
  32. print(cls)
  33.  
  34. @staticmethod
  35. def func1(x,y):
  36. print(x+y)
  37.  
  38. print(Foo.func1)
  39. # <function Foo.func1 at 0x0000023D73765840>

  

二:绑定方法

绑定给对象的方法(略)

绑定给类的方法(classmethod)

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

  1. HOST='127.0.0.1'
  2. PORT=3306
  3. DB_PATH=r'C:\Users\Administrator\PycharmProjects\test\面向对象编程\test1\db'

  

  1. import settings
  2. class MySQL:
  3. def __init__(self,host,port):
  4. self.host=host
  5. self.port=port
  6.  
  7. @classmethod
  8. def from_conf(cls):
  9. print(cls)
  10. return cls(settings.HOST,settings.PORT)
  11.  
  12. print(MySQL.from_conf) #<bound method MySQL.from_conf of <class '__main__.MySQL'>>
  13. conn=MySQL.from_conf()
  14.  
  15. conn.from_conf() #对象也可以调用,但是默认传的第一个参数仍然是类

  

三:非绑定方法

  在类内部用staticmethod装饰的函数即非绑定方法,就是普通函数

  statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果

  1. import hashlib
  2. import time
  3. class MySQL:
  4. def __init__(self,host,port):
  5. self.id=self.create_id()
  6. self.host=host
  7. self.port=port
  8. @staticmethod
  9. def create_id(): #就是一个普通工具
  10. m=hashlib.md5(str(time.time()).encode('utf-8'))
  11. return m.hexdigest()
  12.  
  13. print(MySQL.create_id) #<function MySQL.create_id at 0x0000000001E6B9D8>
  14. #查看结果为普通函数
  15. conn=MySQL('127.0.0.1',3306)
  16. print(conn.create_id) #<function MySQL.create_id at 0x00000000026FB9D8>
  17. #查看结果为普通函数

  

四:绑定方法与非绑定方法的使用举例

  1. import settings
  2. import hashlib
  3. import time
  4. class People:
  5. def __init__(self,name,age,sex):
  6. self.id =self.create_id()
  7. self.name = name
  8. self.age = age
  9. self.sex = sex
  10. def tell_info(self): #绑定到对象啊
  11. print("name:%s Age:%s Sex:%s"%(self.name,self.age,self.sex))
  12. @classmethod
  13. def from_conf(cls):
  14. obj = cls(
  15. settings.name,
  16. settings.age,
  17. settings.sex
  18. )
  19. return obj
  20. @staticmethod
  21. def create_id():
  22. m = hashlib.md5(str(time.time()).encode('utf-8'))
  23. return m.hexdigest()
  24. p = People('tom',18,'male')
  25. #绑定到对象,就应该由对象来调用,自动将对象本身当作第一个参数传入
  26. # p.tell_info() #tell_info(p)
  27. #绑定给类,就应该由类来调用,自动将类本身当作第一个参数传入
  28. # p1 = People.from_conf() #from_conf(People)
  29. # p1.tell_info()
  30. #非绑定方法,不与类或者对象绑定,谁都可以调用,没有自动传值这一说
  31. p1 = People('tom1',18,'male')
  32. p2 = People('tom2',18,'male')
  33. p3 = People('tom3',18,'male')
  34. print(p1.id)
  35. print(p2.id)
  36. print(p3.id)
  37. # 08885a46a83b92f94c0f4de537fce9c3
  38. # 08885a46a83b92f94c0f4de537fce9c3
  39. # 2b2df79b379a5f7f709ead6268eb3361

  

五:classmethod 与 staticmethod的区别

  1. import settings
  2. class MySQL:
  3. def __init__(self,host,port):
  4. self.host=host
  5. self.port=port
  6.  
  7. @staticmethod
  8. def from_conf():
  9. return MySQL(settings.HOST,settings.PORT)
  10.  
  11. # @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
  12. # def from_conf(cls):
  13. # return cls(settings.HOST,settings.PORT)
  14.  
  15. def __str__(self):
  16. return '就不告诉你'
  17.  
  18. class Mariadb(MySQL):
  19. def __str__(self):
  20. return '<%s:%s>' %(self.host,self.port)
  21.  
  22. m=Mariadb.from_conf()
  23. print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你:
  24.  
  25. mariadbmysql

  

5.1,类方法,静态方法的定义

Python 是双面向的,既可以面向函数编程,也可以面向对象编程,所谓面向函数就是单独一个. py 文件,里面没有类,全是一些函数,调用的时候导入模块,通过模块名.函数名()即可调用,完全不需要类,那么你可能会问,那要类还有什么毛用? 类就是用来面向对象编程啦,类可以有自己的属性,类可以创建很多实例,每个实例可以有不同的属性,这也就保存了很多私有的数据,总之都有存在的必要.

面向对象程序设计中,类方法和静态方法是经常用到的术语,逻辑上将:类方法只能由类名调用,静态方法可以由类名或者对象名调用。在python 语法中,类有三种方法,分别是实例方法,静态方法,类方法

  1. class Foo(object):
  2. '''类三种方法语法形式'''

  3. #在类中定义普通方法,在定义普通方法的时候,必须添加self  
  4. def instance_method(self):
  5. print("是类{}的实例方法,只能被实例对象调用".format(Foo))

  6.   #在类中定义静态方法,在定义静态方法的时候,不需要传递任何类的东西 
  7. @staticmethod
  8. def static_method():
  9. print("是静态方法")

  10.   #在类中定义类方法,在定义类方法的时候,需要传递参数cls  cls即为类本身
  11. @classmethod
  12. def class_method(cls):
  13. print("是类方法")
  14.  
  15. foo = Foo()
  16. foo.instance_method()
  17. foo.class_method()
  18. foo.static_method()
  19. print("---------------")
  20. Foo.static_method()
  21. Foo.class_method()

  可以看出:

       实例方法只能被实例对象调用,静态方法(由@staticmethod装饰的方法)、类方法(由@classmethod装饰的方法),可以被类或类的实例对象调用。
   实例方法,第一个参数必须要默认传实例对象,一般习惯用self。对象方法中有self参数,类方法有cls参数,静态方法是不需要这些附加参数(在c++中,是没有类这个概念)

静态函数(@staticmethod):即静态方法,静态方法是一类特殊的方法,有时候你可能需要填写一个属于这个类的方法,但是这些代码完全不会使用到实例对象本身。它主要处理这个类的逻辑关联,如验证数据;而且对参数没有要求。

类方法(@classmethod):即类方法,类方法不是绑定到对象上,而是绑定在类上的方法,它更关注于从类中调用方法,而不是从实例中调用方法,如构造重载;

成员函数:实例的方法,只能通过实例进行调用;第一个参数必须要默认传类,一般习惯用cls。

5.2,类方法与静态方法说明

  1:self表示为类型为类的object,而cls表示为类也就是class

  2:在定义普通方法的时候,需要的是参数self,也就是把类的实例作为参数传递给方法,如果不写self的时候,会发现报错TypeError错误,表示传递的参数多了,其实也就是调用方法的时候,将实例作为参数传递了,在使用普通方法的时候,使用的是实例来调用方法,不能使用类来调用方法,没有实例,那么方法将无法调用。

  3:在定义静态方法的时候,和模块中的方法没有什么不同,最大的不同就是在于静态方法在类的命名空间之间,而且在声明静态方法的时候,使用的标记为@staticmethod,表示为静态方法,在叼你用静态方法的时候,可以使用类名或者是实例名来进行调用,一般使用类名来调用

  4:静态方法主要是用来放一些方法的,方法的逻辑属于类,但是有何类本身没有什么交互,从而形成了静态方法,主要是让静态方法放在此类的名称空间之内,从而能够更加有组织性。

  5:在定义类方法的时候,传递的参数为cls.表示为类,此写法也可以变,但是一般写为cls。类的方法调用可以使用类,也可以使用实例,一般情况使用的是类。

  6:在重载调用父类方法的时候,最好是使用super来进行调用父类的方法。静态方法主要用来存放逻辑性的代码,基本在静态方法中,不会涉及到类的方法和类的参数。类方法是在传递参数的时候,传递的是类的参数,参数是必须在cls中进行隐身穿

  7:python中实现静态方法和类方法都是依赖python的修饰器来实现的。静态方法是staticmethod,类方法是classmethod。

5.3,静态方法,类方法的使用区别

1:类方法用在模拟java定义多个构造函数的情况

由于python类中只能有一个初始化方法,不能按照不同的情况初始化类,举例如下:

  1. class book(object):
  2.  
  3. def __init__(self,title):
  4. self.title = title
  5.  
  6. @classmethod
  7. def creat(cls,title):
  8. book = cls(title=title)
  9. return book
  10.  
  11. book1=book("python")
  12. book2 = book.creat("python is my work")
  13. print(book1)
  14. print(book2)
  15. print(book1.title)
  16. print(book2.title)

 2:类中静态方法方法调用静态方法的情况

下面的代码,静态方法调用另一个静态方法,如果改用类方法调用静态方法,可以让cls代替类,(让代码看起来精简一些,也防止类名修改了,不用在类定义中修改原来的类名)

  1. class foo(object):
  2. x =1
  3. u =1
  4.  
  5. @staticmethod
  6. def average(*mixes):
  7. return sum(mixes)/len(mixes)
  8.  
  9. @staticmethod
  10. def static_method():
  11. return foo.average(foo.x,foo.u)
  12.  
  13. @classmethod
  14. def class_method(cls):
  15. return cls.average(cls.x,cls.u)
  16.  
  17. a = foo()
  18. print(a.static_method())
  19. print(a.class_method())

  

六:练习

定义MySQL类

  1.对象有id、host、port三个属性

  2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一

  3.提供两种实例化方式,方式一:用户传入host和port 方式二:从配置文件中读取host和port进行实例化

  4.为对象定制方法,save和get_obj_by_id,save能自动将对象序列化到文件中,文件路径为配置文件中DB_PATH,文件名为id号,保存之前验证对象是否已经存在,若存在则抛出异常,;get_obj_by_id方法用来从文件中反序列化出对象

小提示:创建唯一id之UUID

  1. 原文链接:http://www.cnblogs.com/dkblog/archive/2011/10/10/2205200.html
  2. Python官方Doc:《20.15. uuid UUID objects according to RFC 4122
  3. UUID的算法介绍:《A Universally Unique IDentifier (UUID) URN Namespace
  4.  
  5. 概述:
  6.  
  7. UUID128位的全局唯一标识符,通常由32字节的字符串表示。
  8. 它可以保证时间和空间的唯一性,也称为GUID,全称为:
  9. UUID —— Universally Unique IDentifier Python 中叫 UUID
  10. GUID —— Globally Unique IDentifier C# 中叫 GUID
  11.  
  12. 它通过MAC地址、时间戳、命名空间、随机数、伪随机数来保证生成ID的唯一性。
  13. UUID主要有五个算法,也就是五种方法来实现:
  14.  
  15. 1uuid1()——基于时间戳
  16.  
  17. MAC地址、当前时间戳、随机数生成。可以保证全球范围内的唯一性,
  18. MAC的使用同时带来安全性问题,局域网中可以使用IP来代替MAC
  19.  
  20. 2uuid2()——基于分布式计算环境DCEPython中没有这个函数)
  21.  
  22. 算法与uuid1相同,不同的是把时间戳的前4位置换为POSIXUID
  23. 实际中很少用到该方法。
  24.  
  25. 3uuid3()——基于名字的MD5散列值
  26.  
  27. 通过计算名字和命名空间的MD5散列值得到,保证了同一命名空间中不同名字的唯一性,
  28. 和不同命名空间的唯一性,但同一命名空间的同一名字生成相同的uuid
  29.  
  30. 4uuid4()——基于随机数
  31.  
  32. 由伪随机数得到,有一定的重复概率,该概率可以计算出来。
  33.  
  34. 5uuid5()——基于名字的SHA-1散列值
  35.  
  36. 算法与uuid3相同,不同的是使用 Secure Hash Algorithm 1 算法
  37.  
  38. 使用方面:
  39.  
  40. 首先,Python中没有基于DCE的,所以uuid2可以忽略;
  41. 其次,uuid4存在概率性重复,由无映射性,最好不用;
  42. 再次,若在Global的分布式计算环境下,最好用uuid1
  43. 最后,若有名字的唯一性要求,最好用uuid3uuid5
  44.  
  45. 编码方法:
  46.  
  47. # -*- coding: utf-8 -*-
  48.  
  49. import uuid
  50.  
  51. name = "test_name"
  52. namespace = "test_namespace"
  53.  
  54. print uuid.uuid1() # 带参的方法参见Python Doc
  55. print uuid.uuid3(namespace, name)
  56. print uuid.uuid4()
  57. print uuid.uuid5(namespace, name)

  

代码:

  1. #settings.py内容
  2. '''
  3. HOST='127.0.0.1'
  4. PORT=3306
  5. DB_PATH=r'E:\CMS\aaa\db'
  6. '''
  7. import settings
  8. import uuid
  9. import pickle
  10. import os
  11. class MySQL:
  12. def __init__(self,host,port):
  13. self.id=self.create_id()
  14. self.host=host
  15. self.port=port
  16.  
  17. def save(self):
  18. if not self.is_exists:
  19. raise PermissionError('对象已存在')
  20. file_path=r'%s%s%s' %(settings.DB_PATH,os.sep,self.id)
  21. pickle.dump(self,open(file_path,'wb'))
  22.  
  23. @property
  24. def is_exists(self):
  25. tag=True
  26. files=os.listdir(settings.DB_PATH)
  27. for file in files:
  28. file_abspath=r'%s%s%s' %(settings.DB_PATH,os.sep,file)
  29. obj=pickle.load(open(file_abspath,'rb'))
  30. if self.host == obj.host and self.port == obj.port:
  31. tag=False
  32. break
  33. return tag
  34. @staticmethod
  35. def get_obj_by_id(id):
  36. file_abspath = r'%s%s%s' % (settings.DB_PATH, os.sep, id)
  37. return pickle.load(open(file_abspath,'rb'))
  38.  
  39. @staticmethod
  40. def create_id():
  41. return str(uuid.uuid1())
  42.  
  43. @classmethod
  44. def from_conf(cls):
  45. print(cls)
  46. return cls(settings.HOST,settings.PORT)
  47.  
  48. # print(MySQL.from_conf) #<bound method MySQL.from_conf of <class '__main__.MySQL'>>
  49. conn=MySQL.from_conf()
  50. conn.save()
  51.  
  52. conn1=MySQL('127.0.0.1',3306)
  53. conn1.save() #抛出异常PermissionError: 对象已存在
  54.  
  55. obj=MySQL.get_obj_by_id('7e6c5ec0-7e9f-11e7-9acc-408d5c2f84ca')
  56. print(obj.host)

  

其他练习

  1. class Date:
  2. def __init__(self,year,month,day):
  3. self.year=year
  4. self.month=month
  5. self.day=day
  6. @staticmethod
  7. def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间
  8. t=time.localtime() #获取结构化的时间格式
  9. return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回
  10. @staticmethod
  11. def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间
  12. t=time.localtime(time.time()+86400)
  13. return Date(t.tm_year,t.tm_mon,t.tm_mday)
  14.  
  15. a=Date('1987',11,27) #自己定义时间
  16. b=Date.now() #采用当前时间
  17. c=Date.tomorrow() #采用明天的时间
  18.  
  19. print(a.year,a.month,a.day)
  20. print(b.year,b.month,b.day)
  21. print(c.year,c.month,c.day)
  22.  
  23. #分割线==============================
  24. import time
  25. class Date:
  26. def __init__(self,year,month,day):
  27. self.year=year
  28. self.month=month
  29. self.day=day
  30. @staticmethod
  31. def now():
  32. t=time.localtime()
  33. return Date(t.tm_year,t.tm_mon,t.tm_mday)
  34.  
  35. class EuroDate(Date):
  36. def __str__(self):
  37. return 'year:%s month:%s day:%s' %(self.year,self.month,self.day)
  38.  
  39. e=EuroDate.now()
  40. print(e) #我们的意图是想触发EuroDate.__str__,但是结果为
  41. '''
  42. 输出结果:
  43. <__main__.Date object at 0x1013f9d68>
  44. '''
  45. 因为e就是用Date类产生的,所以根本不会触发EuroDate.__str__,解决方法就是用classmethod
  46.  
  47. import time
  48. class Date:
  49. def __init__(self,year,month,day):
  50. self.year=year
  51. self.month=month
  52. self.day=day
  53. # @staticmethod
  54. # def now():
  55. # t=time.localtime()
  56. # return Date(t.tm_year,t.tm_mon,t.tm_mday)
  57.  
  58. @classmethod #改成类方法
  59. def now(cls):
  60. t=time.localtime()
  61. return cls(t.tm_year,t.tm_mon,t.tm_mday) #哪个类来调用,即用哪个类cls来实例化
  62.  
  63. class EuroDate(Date):
  64. def __str__(self):
  65. return 'year:%s month:%s day:%s' %(self.year,self.month,self.day)
  66.  
  67. e=EuroDate.now()
  68. print(e) #我们的意图是想触发EuroDate.__str__,此时e就是由EuroDate产生的,所以会如我们所愿
  69. '''
  70. 输出结果:
  71. year:2017 month:3 day:3
  72. '''

  

python 面向对象之多态与绑定方法的更多相关文章

  1. python基础18 ---多态与绑定方法

    一.抽象类 1.抽象类的定义:从一堆类中抽象出相同的内容,重新组成一个新的类,这样的类属于抽象类. 2.香蕉类是一类水果,苹果类是一类水果,葡萄类是一类水果,但是他们都属于水果,从他们这些类中可以抽象 ...

  2. Python面向对象之常用的特殊方法(5)

    Python面向对象里面有很多特殊方法,例如__init__(构造方法),__del__(析构方法),这些方法对于面向对象编程非常重要,下面列出一些常用的特殊方法 (1)__call__ class ...

  3. Python基础(17)_面向对象程序设计(抽象类、继承原理、封装、多态,绑定方法)

    一.抽象类 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化 1.在python中实现抽象类 import abc #利用abc模块实现抽象类 class All_file(metacl ...

  4. python面向编程:面向对象、init、绑定方法、案例练习

    一.类的定义 二.面向对象概念三.对象的使用四.__init__函数的使用五.绑定方法六.面向对象联系 一.类的定义 1.什么叫做类? 类就是分类,类型的意思,一堆具备相同特征和行为的事物的抽象概念 ...

  5. python中类与对象及其绑定方法的定义

    面向对象编程 什么是面向对象? 面向过程:将需要解决的问题按步骤划分,一步一步完成每一个步骤,而且          步骤之间有联系. 优点:复杂问题可以分步完成 缺点:扩展性很差,维护性差.如果中间 ...

  6. python 封装,隐藏属性,绑定方法classmethod和staticmethod

    [封装] 隐藏对象的属性和实现细节,仅对外提供公共访问方式. [好处] 1. 将变化隔离: 2. 便于使用: 3. 提高复用性: 4. 提高安全性: [封装原则] 1. 将不需要对外提供的内容都隐藏起 ...

  7. Python面向对象之多态

    多态 面向对象三大特性 封装 根据职责将属性和方法封装到一个抽象的类中:--定义类的准则 继承 实现代码的重用,相同的代码不需要重复的编写:--设计类的技巧:子类针对自己的需求,编写特定的代码: 多态 ...

  8. python 3 属性查找与绑定方法

    1.属性查找 类有两种属性:数据属性和函数属性 (1)类的数据属性是所有对象共享的 #类的数据属性是所有对象共享的,id都一样 class OldboyStudent: school='oldboy' ...

  9. python3 多态,绑定方法与非绑定方法

    多态:同一种事物的不同形态(一个抽象类有多个子类,因而多态的概念依赖于继承) 1. 序列类型有多种形态:字符串,列表,元组. 2. 动物有多种形态:人,狗,猪 多态性:多态性是指具有不同功能的函数可以 ...

随机推荐

  1. R实战 第五篇:绘图(ggplot2)

    ggplot2包实现了基于语法的.连贯一致的创建图形的系统,由于ggplot2是基于语法创建图形的,这意味着,它由多个小组件构成,通过底层组件可以构造前所未有的图形.ggplot2可以把绘图拆分成多个 ...

  2. Hadoop之Secondary NameNode

    NameNode存储文件系统的变化作为log追加在本地的一个文件里:这个文件是edits.当一个NameNode启动时,它从一个映像文件:FsImage,读取HDFS的状态,使用来自edits日志文件 ...

  3. input依次输入密码

    原理: 一个真正的可以输入的input框,opacity: 0,设定位层级:(视图不可见的) 再来6(n)个input,readyonly,用来显示,type为password,设置好样式:(视图可见 ...

  4. 18.C++-[ ]操作符使用 、函数对象与普通函数区别(详解)

    在上章17.C++-string字符串类(详解)学习了string类,发现可以通过[ ]重载操作符来访问每个字符. 比如: string s="SAD"; for(int i=0, ...

  5. 【Python】 迭代器&生成器

    迭代器 任何一个类,只要其实现了__iter__方法,就算是一个可迭代对象.可迭代对象的__iter__方法返回的对象是迭代器,迭代器类需要实现next方法.一般来说,实现了__iter__方法的类肯 ...

  6. 基于hi-nginx的web开发(python篇)——表单处理和文件上传

    hi-nginx会自动处理表单,所以,在hi.py框架里,要做的就是直接使用这些数据. 表单数据一般用GET和POST方法提交.hi-nginx会把这些数据解析出来,放在form成员变量里.对pyth ...

  7. Java基础笔记(7)----三个修饰符

    abstract抽象 方法 抽象方法:abstract修饰的方法,只有声明 而没有方法的实现(连{}都没有). 语法:修饰符 返回值类型 方法名(形参列表); 注意:抽象方法 必须定义在 抽象类中. ...

  8. Eclipse项目中web app libraries和 Referenced Libraries区别

    Referenced  Libraries是编译环境下使用的JAR包,所谓编译环境下使用的JAR包, 就是说你在Eclipse中进行源文件的编写的时候,所需要引用到的类都从Referenced  Li ...

  9. Rails 定时任务——whenever实现周期性任务

    根据项目的进展,我们需要实现后台进行定时读取信息的功能,而最关键的实现部分是周期性功能,根据调研,决定使用whenever来实现这一功能. github:https://github.com/java ...

  10. C语言数据类型作业

    一.PTA实验作业 题目1:7-4 打印菱形图案 1. 本题PTA提交列表 2. 设计思路 1.定义m,n(用于计算空格数,输出"* "数),i,j,k(用于循环) 2.输入n,并 ...