当前位置: 澳门新濠3559 > 编程 > 正文

两手交换牌,面向过程的思路是将数据与函数按

时间:2019-12-08 22:39来源:编程
======封装思想、构造函数========= 第1题.问题:两手交换牌 1.1面向对象编程介绍 1.继承介绍以及单继承。 将共性的内容放在父类中,子类只需要关注自己特有的内容python中所有的内容都

======封装思想、构造函数=========
第1题.问题:两手交换牌

1.1面向对象编程介绍

1.继承介绍以及单继承。

将共性的内容放在父类中,子类只需要关注自己特有的内容python中所有的内容都是对象,所有的对象都直接或间接继承了object。


1.定义类(个人理解:指代具体事物的单体,属性指的是类的单体的构成部分,题目中明显看到的有手和牌两个事物,以及交换这个动作,那么我们就知道交换的动作是人制造的,然后手有牌,牌有花色和数字,之所以把人牵扯进来,是因为交换的动作需要人来进行,而动作可以视为人这个类的一个函数,所以需要加入人的类)
1)定义牌类(一张牌分为颜色和数字,所以需要做拼接)
属性:花色、数字(一般赋值为空,或设置变量,不会赋具体数值,具体数值由对象来做)

·面向过程:根据业务逻辑从上到下写代码

2.继承示例

# 定义一个父类,如下:

class Cat(object):

def __init__(self, name, color="白色"):

self.name = name

self.color = color

def run(self):

print("%s--在跑"%self.name)

# 定义一个子类,继承Cat类如下:

class Bosi(Cat):

def setNewName(self, newName):

self.name = newName

def eat(self):

print("%s--在吃"%self.name)

bs = Bosi("印度猫")

print('bs的名字为:%s'%bs.name)

print('bs的颜色为:%s'%bs.color)

bs.eat()

bs.setNewName('波斯')

bs.run()

运行结果是:

澳门新濠3559 1

说明:

虽然子类没有定义__init__方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi的对象,就默认执行了那个继承过来的__init__方法

总结

子类在继承的时候,在定义类时,小括号()中为父类的名字

父类的属性、方法,会被继承给子类。

私有的属性,不能通过对象直接访问,但是可以通过方法访问

私有的方法,不能通过对象直接访问

私有的属性、方法,不会被子类继承,也不能被访问

一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用


围绕一门语言学习它的文化精髓能让你成为一名更优秀的程序员更进一步,如果你还没读过Python之禅(Zen of Python) ,那么打开Python的命令提示符输入import this,列表中的每一项你都可以在这里找个相对应的例子。

2)定义手类(这里指的是一只手,而发生交换这个动作必须要人的两只手,不需要创建两个相同的类,所以必然需要创建两个对象)
属性:卡牌

·面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程

3.多继承

class Horse:

def __init__(self,strong):

self.strong=strong

def run(self):

print('跑得快')

class Donkey:

def __init__(self,ear):

self.ear=ear

def pull(self):

print('拉磨')

class Mule(Horse,Donkey):

pass

mule=Mule(True)

print(mule.strong)

mule.run()

mule.pull()

运行结果是:

True

跑得快

拉磨


1.(Credit: itswater ) 吸引我注意力的一条是:

3)定义人类(一个人类有两只手,所以属性中需要分别定义左手和右手用来组成人类的手部)
属性:左手、右手(变量、构造函数)
动作:交换卡牌(函数)

面向过程的思路是将数据与函数按照执行的逻辑顺序组织在一起,数据与函数分开考虑。

4.重写父类方法

所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法。

class Father:

def __init__(self,money):

self.money=money

def f1(self):

print('Father.....f1')

class Son(Father):

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

self.name=name

self.age=age

Father.__init__(self,money)

def f1(self):

print('Son......f1')

Father.f1(self)

def __str__(self):

return '%s,%s,%s'%(self.money,self.name,self.age)

son=Son('小王',23,4234234)

son.f1()

print(son)

运行结果是:

Son......f1

Father.....f1

4234234,小王,23


优雅胜于丑陋 (Beautiful is better than ugly)

2.创建类和函数

def发送邮件(内容)

5.多态

什么是封装?

类是一种封装,将属性和方法封装。

函数也是一种封装,将具有一定共的逻辑代码封装到一个函数中,使用的时候调用即可

提高代码的扩展性。

什么是继承?

将公共的(共性的)属性和方法放在父类中,子类只关注自己特有的属性和方法。

提高代码的扩展性。

什么是多态?

一个对象在不同的情况下,具有不同的形态,用于强类型语言。是使用在继承和接口中实现。

Python中有两种说法:

1、python支持多态,python是一个弱类型,本身一个变量名,可以存储任何类型的值,可以理解为多种形态

2、python不支持多态,多态本身是用于强类型语言的,python是一个弱类型,所以不支持多态


看下面例子:

1)创建卡牌类
定义属性:分为花色和数字
class pai: #创建牌类
def init(self): #创建构造函数
self.colors=None #定义牌的花色变量为空
self.nums=None #定义牌的数字变量为空

#发送邮件提醒

6.类属性、实例属性.

直接在类中定义的,与方法平齐,不在方法里的属性就是 类属性

在方法里通过self.属性 都是实例属性

class Dog:

def __init__(self,name,color):

self.name=name

self.color=color

#创建一个实例对象

d1=Dog('旺财','黑色')

print(d1.name)

print(d1.color)

#实例属性

d1.num=10

print(d1.num)

d2=Dog('小白','白色')

print(d2.name)

运行结果是:

旺财

黑色

10

小白


class Person:

sun=1

p1=Person()

p2=Person()

print(p1.sun)

print(p2.sun)

print(Person.sun)

print('******************************************')

Person.sun=0

print(p1.sun)

print(p2.sun)

print('*************************************')

p1.sun=1111

print(p1.sun)

print(p2.sun)

print(Person.sun)

运行结果是:

1

1

1

******************************************

0

0

*************************************

1111

0

0

7.

一个带有数字参数的list函数其功能是返回参数中的奇数可以分开写:

2)创建手类
定义属性:牌
class hand: #创建手类
def init(self): #定义构造函数
self.pai="" #定义牌变量为空

连接邮箱服务器

1.#----------------------------------------------------------------------- 

3)创建人类
定义属性:左手和右手
class Persion: #创建人类
def init(self): #创建构造函数
self.left_hand=None #定义左手变量为空
self.right_hand=None #定义右手变量为空

两手交换牌,面向过程的思路是将数据与函数按照执行的逻辑顺序组织在一起澳门新濠3559:。发送邮件

  1. halve_evens_only = lambda nums: map(lambda i: i/2,  3. filter(lambda i: not i%2, nums))  4. #-----------------------------------------------------------------------  5.def halve_evens_only(nums):  6.     return [i/2 for i in nums if not i % 2] 记住Python中那些非常简单的事

创建动作:交换
def change(self): #创建函数
c=self.left_hand #将变量c赋值为左手
self.left_hand=self.right_hand #将变量左手赋值为变量右手
self.right_hand=c #将变量c赋值为右手

关闭连接

两个变量的交换:

3.创建对象
1)卡牌对象
第一个牌对象(第一张牌)
p1=pai() #创建牌类对象
p1.colors="黑" #将color赋值为黑
p1.nums="3" #将nums赋值为3

while True:

1.1 a, bb = b, a  参数在切片操作中的步骤,如:

第二个牌对象(第二张牌)
p2=pai() #创建牌类对象
p2.colors="黑" #将color赋值为黑
p2.nums="4" #将nums赋值为4

if cpu利用率> 90%:

1.a = [1,2,3,4,5]  2.>>> a[::2]  # 以步长为2的增量迭代整个list对象  3.[1,3,5] 一个特殊的例子 `x[::-1]`用来反转x的实用语法。

2)手类对象
第一个手对象(第一只手)
l=hand() #创建手类对象(左手)
l.pai=p1.colors+p1.nums #将牌的变量赋值为牌类的变量花色和数字的拼接(l为对象,pai为类中定义的构造函数变量,l.pai就相当于self.pai,这里是讲类中的变量模板拿出来进行赋值,类里面的self.pai为空值,这里就是通过对象,将其调用进行具体赋值了,这里有两只手,就对类中的变量进行两次赋值,两次对象的赋值都是独立进行的,左手赋值会保持一个变量,右手赋值会再保持一个变量,这也是扩展性的一个体现,不需要更改类里面的模板,只需要通过创建对象就可以不断的扩展

发送邮件('CPU报警')

1.a = [1,2,3,4,5]  2.>>> a[::2]  # 以步长为2的增量迭代整个list对象  3.[1,3,5] 不要用可变对象作为默认参数值(Don’t use mutable as defaults)

第二个手对象(第二只手)
r=hand() #创建手类对象(右手)
r.pai=p2.colors+p2.nums #将牌的变量赋值为牌类的变量花色和数字的拼接

if硬盘使用空间> 90%:

1.def function(x, l=[]):          # 不要这么干  2.def function(x, l=None):        # 更好的一种方式  3.    if l is None:  4.       l = [] 而不是items

3)人类对象
d1=Persion() #创建人类对象
d1.right_hand=l #将右手赋值给手类(左手)对象
d1.left_hand=r #将左手赋值给手类(右手)对象
d1.change() #将左右手交换(调用交换函数)
print(d1.left_hand.pai,d1.right_hand.pai) #打印左手和右手的牌

发送邮件('硬盘报警')

iteriterms 使用的是 generators,所以当迭代很大的序列是此方法更好

if内存占用> 80%:

1.d = {1: "1", 2: "2", 3: "3"}  2. 3.for key, val in d.items() # 调用items()后会构建一个完整的list对象  4. 5.for key, val in d.iteritems() # 只有在迭代时每请求一次才生成一个值  此情景和range与xrange的关系相似。

发送邮件('内存报警')

使用isinstance 而不是type

面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)

不要这样做:

面向对象(object-oriented ;简称: OO)指按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。

1.if type(s) == type(""): ...  2.if type(seq) == list or   3.type(seq) == tuple: ...  应该是这样:

面向对象编程(Object Oriented Programming-OOP)是一种解决软件复用的设计和编程方法。这种方法把软件系统中相近相似的操作逻辑和操作应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。

1.if isinstance(s, basestring): ...  2.if isinstance(seq, (list, tuple)): ...  至于为什么这样做,看这里:

面向对象的理解:

需要注意的是这里使用basestring而不是str是因为你可能会用一个unicode对象去检查是否为string,例如:

面向对象是一种设计思想

  1. >>> a=u'aaaa' 2.>>> print isinstance(a, basestring)  3.True  4.>>> print isinstance(a, str)  5.False  因为在Python中3.0以下的版本存在两种字符串类型str和unicode

1.符合人们的思考习惯

object

2.把执行者变成指挥者

|

3.简化功能,把复杂的事情简单化

basestring

面向对象有三大特征:

/

1.封装

str unicode

2.继承

学习各种集合(learn the various collections)

3.多态

python有各种各样的容器数据类型,在特定情况下选择python内建的容器如:list和dict。通常更多像如下方式使用:

1.2类和对象

1.freqs = {}  2.for c in "abracadabra":  3.try:  4.freqs[c] += 1  5.except:  6.freqs[c] = 1  一种更好的方案如下:

对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类

1.freqs = {}  2.for c in "abracadabra":  3.freqs[c] = freqs.get(c, 0)

类是对事务的描述,是抽象的。

  • 1  一种更好的选择 collection类型defautdict:

对象是类的具体体现。

1.from collections import defaultdict  2.freqs = defaultdict(int)  3.for c in "abracadabra":  4.freqs[c] += 1  其它集合

1.2.1类

1.namedtuple() # 用指定的域创建元组子类的工厂函数  2.deque # 类似list的容器,快速追加以及删除在序列的两端  3.Counter # 统计哈希表的dict子类  4.OrderedDict # 记录实体添加顺序的dict子类  5.defaultdict # 调用工厂方法为key提供缺省值的dict子类  当创建类时Python的魔术方法:

类:

1.__eq__(self, other) # 定义相等操作的行为, ==.  2.__ne__(self, other) # 定义不相等操作的行为, !=.  3.__lt__(self, other) #定义小于操作的行为, <. 4.__gt__(self, other) #定义不大于操作的行为, >.  5.__le__(self, other) #定义小于等于操作的行为, <=.  6.__ge__(self, other) #定义大于等于操作的行为, >=.  条件赋值

具有相似内部状态和运动规律的实体的集合(或统称为抽象)。

1.x = 3 if (y == 1) else 2   2. 表达式请起来恰恰像:如果y等于1就把3赋值给x,否则把2赋值给x,当然同样可以使用链式条件赋值如果你还有更复杂的条件的话。

具有相同属性和行为事物的统称

1.x= 3 if (y == 1) else 2 if (y == -1) else 1   然而到了某个特定的点,它就有点儿过分了。

类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象

记住,你可以在任何表达式中使用if-else例如:

1.2.2对象

1.(func1 if y == 1 else func2)(arg1, arg2)   2. func1将被调用如果y等于1的话,反之func2被调用。两种情况下,arg1和arg2两个参数都将附带在相应的函数中。

对象:

类似地,下面这个表达式同样是正确的

某一个具体事物的存在,在现实世界中可以是看得见摸得着的。

1.x = (class1 if y == 1 else class2)(arg1, arg2)  class1和class2是两个类

可以是直接使用的

在有必要的时侯使用Ellipsis

1.2.3类和对象之间的关系

创建类时,你可以使用__getitem__,让你的类像字典一个工作,拿下面这个类举例来说:

类就是创建对象的模板

1.class MyClass(object):  2.def __init__(self, a, b, c, d):  3.self.a, self.b, self.c, self.d = a, b, c, d  4. 5.def __getitem__(self, item):  6.return getattr(self, item)  7. 8.x = MyClass(10, 12, 22, 14) 因为有了__getitem__,你就能够通过对象x的x[‘a’]获取a的值,这应该是公认的事实。

1.2.4类的构成

这个对象通常用于继承Python的切片(slicing) (),如果添加如下语句:

类(Class)由3个部分构成

1.def __getitem__(self, item):  2.if item is Ellipsis:  3.return [self.a, self.b, self.c, self.d]  4.else:  5.return getattr(self, item)  我们就可以使用x[…]获取的包含所有项的序列

·类的名称:类名

1.>>> x = MyClass(11, 34, 23, 12)  2.>>> x[...]  3.[11, 34, 23, 12]  英文出自:Satyajit Ranjeev

·类的属性:一组数据成员变量

译文出自:伯乐在线

·类的方法:允许对进行操作的方法(行为)成员方法

 

1.2.5类的抽象

拥有相同(或者类似)属性和行为的对象都可以抽像出一个类

方法:一般名词都是类(名词提炼法)

1.3定义类

定义一个类,格式如下:

class类名:

方法列表

demo:定义一个Car类

#定义类

classCar:

#方法

defgetCarInfo(self):

print('车轮子个数:%d,颜色%s'%(self.wheelNum, self.color))

defmove(self):

print("车正在移动...")

说明:

·定义类时有2种:新式类和经典类,上面的Car为经典类,如果是Car(object)则为新式类

·类名的命名规则按照"大驼峰"

1.4创建对象

创建对象的格式为:

对象名=类名()

创建对象demo:

#定义类

classCar:

#移动

defmove(self):

print('车在奔跑...')

#鸣笛

deftoot(self):

print("车在鸣笛...嘟嘟..")

#创建一个对象,并用变量BMW来保存它的引用

BMW = Car()

BMW.color ='黑色'

BMW.wheelNum =4#轮子数量

BMW.move()

BMW.toot()

print(BMW.color)

print(BMW.wheelNum)

总结:

·BMW = Car(),这样就产生了一个Car的实例对象,此时也可以通过实例对象BMW来访问属性或者方法

·第一次使用BMW.color

= '黑色'表示给BMW这个对象添加属性,如果后面再次出现BMW.color = xxx表示对属性进行修改

·BMW是一个对象,它拥有属性(数据)和方法(函数)

·当创建一个对象时,就是用一个模子,来制造一个实物

1.5__init__()方法

在创建对象的时候,直接设置对象的属性。

1.5.1使用方式

def类名:

#初始化函数,用来完成一些默认的设定

def__init__():

pass

1.5.2__init__()方法的调用

#定义汽车类

classCar:

def__init__(self):

self.wheelNum =4

self.color ='蓝色'

defmove(self):

print('车在跑,目标:夏威夷')

#创建对象

BMW = Car()

print('车的颜色为:%s'%BMW.color)

print('车轮胎数量为:%d'%BMW.wheelNum)

1.5.3总结1

当创建Car对象后,在没有调用__init__()方法的前提下,BMW就默认拥有了2个属性wheelNum和color,原因是__init__()方法是在创建对象后,就立刻被默认调用了

调用__init__()方法时传参:

#定义汽车类

classCar:

def__init__(self, newWheelNum, newColor):

self.wheelNum = newWheelNum

self.color = newColor

defmove(self):

print('车在跑,目标:夏威夷')

#创建对象

BMW = Car(4,'green')

print('车的颜色为:%s'%BMW.color)

print('车轮子数量为:%d'%BMW.wheelNum)

1.5.4总结2

·__init__()方法,在创建一个对象时默认被调用,不需要手动调用

·__init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)中出了self作为第一个形参外还需要2个形参,例如__init__(self,x,y)

·__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去

1.6"魔法"方法

1.6.1打印id()

print(对象名)

1.6.2定义__str__()方法

classCar:

def__init__(self, newWheelNum, newColor):

self.wheelNum = newWheelNum

self.color = newColor

def__str__(self):

msg ="嘿。。。我的颜色是"+ self.color +"我有"+ int(self.wheelNum) +"个轮胎..."

returnmsg

defmove(self):

print('车在跑,目标:夏威夷')

BMW = Car(4,"白色")

print(BMW)

1.6.3总结

·在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法

·当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据

·

1.7self

1.7.1理解self

示例:

#定义一个类

classAnimal:

#方法

def__init__(self, name):

self.name = name

defprintName(self):

print('名字为:%s'%self.name)

#定义一个函数

defmyPrint(animal):

animal.printName()

dog1 = Animal('西西')

myPrint(dog1)

dog2 = Animal('北北')

myPrint(dog2)

self表示是当前对象

1.7.2总结

·所谓的self,可以理解为自己

·可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思

·某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可

1.8保护对象的属性

如果有一个对象,当需要对其进行修改属性时,有2种方法

·对象名.属性名=数据---->直接修改

·对象名.方法名() ---->间接修改

为了更好的保存属性安全,即不能随意修改,一般的处理方式为

·将属性定义为私有属性

·添加一个可以调用的方法,供调用

classPeople(object):

def__init__(self, name):

self.__name = name

defgetName(self):

returnself.__name

defsetName(self, newName):

iflen(newName) >=5:

self.__name = newName

else:

print("error:名字长度需要大于或者等于5")

xiaoming = People("xx")

print(xiaoming.__name)

classPeople(object):

def__init__(self, name):

self.__name = name

defgetName(self):

returnself.__name

defsetName(self, newName):

iflen(newName) >=5:

self.__name = newName

else:

print("error:名字长度需要大于或者等于5")

xiaoming = People("xx")

xiaoming.setName("yy")

print(xiaoming.getName())

xiaoming.setName("lisi")

print(xiaoming.getName())

总结

·Python中没有像关键字来区别公有属性和私有属性

·它是以属性命名方式来区分,如果在属性名前面加了2个下划线'__',则表明该属性是私有属性,否则为公有属性(方法也是一样,方法名前面加了2个下划线的话表示该方法是私有的,否则为公有的)。

1.9__del__()方法

创建对象后,python解释器默认调用__init__()方法;

当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法

importtime

classAnimal(object):

#初始化方法

#创建完对象后会自动被调用

def__init__(self, name):

print('__init__方法被调用')

self.__name = name

#析构方法

#当对象被删除时,会自动被调用

def__del__(self):

print("__del__方法被调用")

print("%s对象马上被干掉了..."%self.__name)

#创建对象

dog = Animal("哈皮狗")

#删除对象

deldog

cat = Animal("波斯猫")

cat2 = cat

cat3 = cat

print("---马上删除cat对象")

delcat

print("---马上删除cat2对象")

delcat2

print("---马上删除cat3对象")

delcat3

print("程序2秒钟后结束")

time.sleep(2)

总结

·当有1个变量保存了对象的引用时,此对象的引用计数就会加1

·当使用del删除变量指向的对象时,如果对象的引用计数不会1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除,__del__会被调用

1.10继承介绍以及单继承

为什么要继承:

将共性的内容放在父类中,子类只需要关注自己特有的内容

1.10.1继承的概念

继承描述的是事物之间的所属关系。

1.10.2继承示例

#定义一个父类,如下:

classCat(object):

def__init__(self, name, color="白色"):

self.name = name

self.color = color

defrun(self):

print("%s--在跑"%self.name)

#定义一个子类,继承Cat类如下:

classBosi(Cat):

defsetNewName(self, newName):

self.name = newName

defeat(self):

print("%s--在吃"%self.name)

bs = Bosi("印度猫")

print('bs的名字为:%s'%bs.name)

print('bs的颜色为:%s'%bs.color)

bs.eat()

bs.setNewName('波斯')

bs.run()

说明:

·虽然子类没有定义__init__方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi的对象,就默认执行了那个继承过来的__init__方法

总结

·子类在继承的时候,在定义类时,小括号()中为父类的名字

·父类的属性、方法,会被继承给子类

1.10.3注意点

classAnimal(object):

def__init__(self, name='动物', color='白色'):

self.__name = name

self.color = color

def__test(self):

print(self.__name)

print(self.color)

deftest(self):

print(self.__name)

print(self.color)

classDog(Animal):

defdogTest1(self):

#print(self.__name) #不能访问到父类的私有属性

print(self.color)

defdogTest2(self):

#self.__test() #不能访问父类中的私有方法

self.test()

A = Animal()

#print(A.__name) #程序出现异常,不能访问私有属性

print(A.color)

#A.__test() #程序出现异常,不能访问私有方法

A.test()

print("------分割线-----")

D = Dog(name ="小花狗", color ="黄色")

D.dogTest1()

D.dogTest2()

总结

·私有的属性,不能通过对象直接访问,但是可以通过方法访问

·私有的方法,不能通过对象直接访问

·私有的属性、方法,不会被子类继承,也不能被访问

·一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用

1.11多继承

所谓多继承,即子类有多个父类,并且具有它们的特征

多继承的格式如下:

#定义一个父类

classA:

defprintA(self):

print('----A----')

#定义一个父类

classB:

defprintB(self):

print('----B----')

#定义一个子类,继承自A、B

classC(A,B):

defprintC(self):

print('----C----')

obj_C = C()

obj_C.printA()

obj_C.printB()

运行结果:

----A----

----B----

说明

·python中是可以多继承的,在java中叫接口

·父类中的方法、属性,子类会继承

1.12重写/覆盖父类方法与调用父类方法

1.12.1重写父类方法

所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

#coding=utf-8

classCat(object):

defsayHello(self):

print("halou-----1")

classBosi(Cat):

defsayHello(self):

print("halou-----2")

bosi = Bosi()

bosi.sayHello()

1.12.2调用父类的方法

#coding=utf-8

classCat(object):

def__init__(self,name):

self.name = name

self.color ='yellow'

classBosi(Cat):

def__init__(self,name):

#调用父类的__init__方法1(python2)

#Cat.__init__(self,name)

#调用父类的__init__方法2

#super(Bosi,self).__init__(name)

#调用父类的__init__方法3

super().__init__(name)

defgetName(self):

returnself.name

bosi =

Bosi('xiaohua')

print(bosi.name)

print(bosi.color)

1.13多态

Python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型。

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。

在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。

所谓多态:定义时的类型和运行时的类型不一样,就成为多态

·Python伪代码实现Java或C#的多态

packagedemo1;

/*

多态:多种形态,必须依赖于继承完成的。

场景:

Animal

|Dog

|Cat

*/

classAnimal{

public void eat(){

System.out.println("animaleat...");

}

}

class Dogextends Animal{

public void eat(){

System.out.println("Dogeat...");

}

}

class Catextends Animal{

public void eat(){

System.out.println("Cateat...");

}

}

classMyTest{

public static void tt(Animal animal){

animal.eat();

}

public static void main(String[] args){

Animal a = new Animal();

tt(a);// animal eat...

Animal d = new Dog();

tt(d);// Animal animal = dDog eat...

d = new Cat();

tt(d);// Cat eat...

//int num= 10;

//tt(num);

}

}

/**

* java,c#都是强类型语言,就是说在变量定义的时候必须类型名字

*这样,在传递参数的时候,都类型有要求

*

*所在在这样的语言中,多态的表现有两种:

*1、父类作为参数,既可以传递父类对象,也可以传递子类对象

*这样,在方法中,调用的是子和父都有的方法,

*如果传递的是父类对象,调用的就是父类的方法

*如果传递的是子类对象,调用的就是子类的方法

*

*/

·Python “鸭子类型”

‘’’

python是一种弱类型语言,没有类型限制。

变量的类型永远是通过右侧的值判断的。

方法中的参数,传递任何值都行。但是要考虑方法内部的业务逻辑。

多态:

1、父类作为参数,可以传递父类和子类对象

2、接口作为参数,只能传递实现对象

所以有两种理解:

1、python不支持多态:

python是弱类型,没有类型限定,无法区分父和子,或者说接口和实现类

2、python处处是多态

python是弱类型,没有类型限定,传递任何内容都行

‘’’

classF1(object):

def show(self):

print('F1.show')

classS1(F1):

def show(self):

print('S1.show')

classS2(F1):

def show(self):

print('S2.show')

deffunc(obj):

obj.show()

#print(type(obj))

s1_obj =S1()

func(s1_obj)

s2_obj =S2()

func(s2_obj)

f1 = F1()

func(f1)

#func(10)能传递值,但是业务逻辑可能不符合

1.14类属性、实例属性

直接在类中定义的,与方法平齐,不在方法里的属性就是类属性

在方法里通过self.属性都是实例属性

类属性和实例属性:

在前面的例子中我们接触到的就是实例属性(对象属性)。顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本。对于公有的类属性,在类外可以通过类对象和实例对象访问

1.14.1类属性

classPeople(object):

name ='Tom'#公有的类属性

__age =12#私有的类属性

p = People()

print(p.name)#正确

print(People.name)#正确

print(p.__age)#错误,不能在类外通过实例对象访问私有的类属性

print(People.__age)#错误,不能在类外通过类对象访问私有的类属性

1.14.2实例属性(对象属性)

classPeople(object):

address ='山东'#类属性

def__init__(self):

self.name ='xiaowang'#实例属性

self.age =20#实例属性

p = People()

p.age =12#实例属性

print(p.address)#正确

print(p.name)#正确

print(p.age)#正确

print(People.address)#正确

print(People.name)#错误

print(People.age)#错误

1.14.3通过实例(对象)去修改类属性

classPeople(object):

country ='china'#类属性

print(People.country)

p = People()

print(p.country)

p.country ='japan'

print(p.country)#实例属性会屏蔽掉同名的类属性

print(People.country)

delp.country#删除实例属性

print(p.country)

总结

·如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

·

1.15静态方法和类方法

1.15.1类方法

类对象所拥有的方法,需要用修饰器@classmethod(注解、元数据)来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,能够通过实例对象和类对象去访问。

classPeople(object):

country ='china'

#类方法,用classmethod来进行修饰

@classmethod

defgetCountry(cls):

print(type(cls))

print(cls)

returncls.country

p = People()

p.country=1

print(p.getCountry())#可以用过实例对象引用china

printPeople.getCountry()#可以通过类对象引用china

类方法还有一个用途就是可以对类属性进行修改:

classPeople(object):

country ='china'

#类方法,用classmethod来进行修饰

@classmethod

defgetCountry(cls):

returncls.country

@classmethod

defsetCountry(cls,country):

cls.country = country

p = People()

print(p.getCountry())#可以用过实例对象引用

print(People.getCountry())#可以通过类对象引用

p.setCountry('japan')

printp.getCountry()

printPeople.getCountry()

1.15.2静态方法

需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数

classPeople(object):

country ='china'

@staticmethod

#静态方法

defgetCountry():

returnPeople.country

printPeople.getCountry()

class People(object):

country = 'china'

__num = 100

#类方法,用classmethod来进行修饰

@classmethod

def getCountry(cls):

print(type(cls))

print(cls)

return cls.country

@staticmethod

def myStaticMethod():

print('myStaticMethod...')

print(People.__num)

p = People()

p.country=1

print(p.getCountry())#可以用过实例对象引用

print(People.getCountry())#可以通过类对象引用

p.myStaticMethod()

People.myStaticMethod()

'''

1、类方法,实例和类对象都能访问

cls:类对象

2、静态方法:不传参,实例和类对象都能访问

'''

总结

类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性,不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用

1.16设计模式

设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。

1.16.1设计模式六大原则

1.设计模式六大原则(1):单一职责原则

即一个类只负责一项职责

2.设计模式六大原则(2):里氏替换原则

所有引用基类的地方必须能透明地使用其子类的对象

3.设计模式六大原则(3):依赖倒置原则

高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

4.设计模式六大原则(4):接口隔离原则

客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

5.设计模式六大原则(5):迪米特法则

一个对象应该对其他对象保持最少的了解。尽量降低类与类之间的耦合。

6.设计模式六大原则(6):开闭原则

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

1.16.2分类

1.创建型模式

主要目的:创建对象

共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

2.结构型模式

主要目的:对象的组成和对象的关系

共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

3.行为型模式

主要目的:对象的行为,对象能做什么

共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

1.17工厂设计模式

工厂函数、工厂类对具体的生成环节进行了封装,这样有利于代码的后需扩展,即把功能划分的更具体。

总结:

在创建对象比较简单的时候,我们直接在主方法中做了,但是很多时候,创建对象需要一些初始化的操作,或者业务逻辑的处理。也就是说,有时候创建一个对象会做比较复杂的操作,这个时候,如果所有对象的创建操作都放在主方法中,就不合适了,可以使用简单工厂模式

简单工厂模式的组成:

1.工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品

2.抽象产品角色:它一般是具体产品继承的父类或者实现的接口。

3.具体产品角色:工厂类所创建的对象就是此角色的实例。

简单工厂的优点和缺点

对象创建比较复杂的时候,可以考虑使用简单工厂

1.优点:

在简单工厂中主函数或者客户端不再负责对象的创建,而是把这个责任交给工厂类,主函数或者客户端在使用对象的时候只从工厂中调用就行了,从而明确了各个类的职责,符合单一职责原则)

2.缺点

由于这个工厂类负责所有对象的创建,那么当子类增多时,我们就需要去修改工厂类的代码,这样呢,就违反了一个原则:开闭原则

这个时候可以使用工厂方法模式

工厂方法模式组成:

1.抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。

2.具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。

3.抽象产品角色:它是具体产品继承的父类或者是实现的接口。

4.具体产品角色:具体工厂角色所创建的对象就是此角色的实例。

工厂方法模式的优点和缺点

3.优点:

解决了简单工厂模式的违反开闭原则

4.缺点

如果需要增加一个具体产品类角色,需要添加这个类和对应的工厂类。代码量大。

1.18__new__的使用

__new__和__init__的作用

classA(object):

def__init__(self):

print("这是init方法")

def__new__(cls):

print("这是new方法")

returnobject.__new__(cls)

A()

总结

·__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

·__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例

·__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

1.19单例设计模式

1.19.1单例是什么

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

1.19.2创建单例-保证只有1个对象

#实例化一个单例

classSingleton(object):

__instance =None

def__new__(cls, age, name):

#如果类数字能够__instance没有或者没有赋值

#那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时

#能够知道之前已经创建过对象了,这样就保证了只有1个对象

ifnotcls.__instance:

cls.__instance = object.__new__(cls)

returncls.__instance

a = Singleton(18,"wangcai")

b = Singleton(8,"wangcai")

print(id(a))

print(id(b))

a.age =19#给a指向的对象添加一个属性

print(b.age)#获取b指向的对象的age属性

1.19.3创建单例时,只执行1次__init__方法

#实例化一个单例

classSingleton(object):

__instance =None

__first_init =False

def__new__(cls, age, name):

ifnotcls.__instance:

cls.__instance = object.__new__(cls)

returncls.__instance

def__init__(self, age, name):

ifnotself.__first_init:

self.age = age

self.name = name

Singleton.__first_init =True

a = Singleton(18,"wangcai")

b = Singleton(8,"xiaoqiang")

print(id(a))

print(id(b))

print(a.age)

print(b.age)

a.age =19

print(b.age)

编辑:编程 本文来源:两手交换牌,面向过程的思路是将数据与函数按

关键词: