您的位置:首页 > 编程语言 > Python开发

Python—对象类别,创建对象,面向对象

2018-03-10 16:27 344 查看

1. 函数

我们在编程过程中,总是会遇到一些相似的,重复的代码段,而重复的代码段是一个程序员在编程的时候尽量避免的,所以我们可以将重复的代码定义为一个函数来精简你的代码,从而函提高应用的模块性和代码的重复利用率。

你可以定义一个由自己想要功能的函数,以下是简单的规则:

函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。

函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。

任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。

函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。

函数内容以冒号起始,并且缩进。

return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

def f(a,b)

f()
#a和b都是默认值
f(1)
#a为0,b为默认值

def f(*args):
total =0
for val in args:
total += val
return total

mylist = [1,3,,4,10]
print(f(*mylist)#如果不加*,就会将mylist当做一个元素传入函数,会是数值和字符串的运算。
注意代码块后面的函数将会覆盖前面的与其相同名字的函数


作用域 - LEGB:

局部作用域–>嵌套作用域(下级可以使用上级的值)–>全局作用域–>内置作用域,值的搜索范围是从内而外的,这个优先顺序同样也适用于变量的使用。

a = 100#全局a

def f()
global a#读取去全局的a
a = 200#若果全局没有a,则定义全局a
b = 'hello'

def g():
nonlocal(b)#读取上级嵌套非全局a
b = 'good'
迪米特法则:最少知道原则,尽量减少全局变量的使用。


在调用内存时,之前的代码会保存现场在栈再去调用函数,调用函数之后才会恢复现场

函数也可以直接或间接调用自己,称为递归调用

#函数的递归调用
def gcd
4000
(x,y):
if x > y:
return gcd(y,x)
elif y % x == 0:
return x
else:
return  gcd( y % x,x)

if __name__ == '__main__':
print(gcd(21,49))


收敛条件:让递归在有限的次数完成或者进行回溯

2.模块

常见内置模块主要有random、math、time、os等等

调用模块主要通过from、import和as

一个模块尽量放与其相关的函数

一个模块中的函数可以被另一个模块调用,需要在模块后面加

if _ name _ == ‘main‘:否则另一个模块执行被调用模块中的变量

3.内存管理

内存简单分为:栈,堆,静态区

引用:对象包含字符串、数值、列表等等,保存在堆空间,并将地址映射到栈中,而变量就是引用栈中对象保存在堆空间的地址,从而调用对象。

值得注意的是如果使用list1 = [0]*10的形式,那么list1只是将栈中[0]的引用地址复制了十份,在对[o]进行添加元素时只会得到一个list1。

通过调用id()函数可以看到对象在内存中的位置,调用sys.getsizeof()函数可以查看对象占用了多少空间

list1 = [0]*10
list2 = list1
ilst1和list2保存在栈中而[0]*10保存在堆空间中

f = list(range(10))
#f申请一块内存
print(list{x for x in range(10)
#如果没有使用上面申请的空间,python将会将这个对象当做垃圾回收,如果不这样做内存空间将会泄漏,会导致程序闪退。

import sys
list1 = [0]*10
list2 = list1
list3 = list2
print(sys.getrefcount(list1))#显示对象的引用计数,实际值比显示值小1


4.对象类别

无论是在计算机环境还是显示生活中,我们可以把世界认为是由对象构成的,在现实生活中无论动物、植物、微生物或是其他的类别,其中每一个单体都可以认为是一个对象。在计算机环境中也是一样,对象组成了计算机环境。其中主要分为以下几类:

4.1字符串

字符串是Python实际应用中非常常见的一种对象类型,一般字符串是用‘’或者“”来创建,不过字符串的引号使用是不能混搭的。

如:

print("i want to learn 'Python',and you?")#单引号和双引号必须分别对应


字符串的运算方式如下表:

a = ‘hello’

b = ‘world’

header 1header 2header 1
+字符串连接print(a +b)
‘hellohello’
*重复输出字符串a *2
‘hellohello’
[]通过索引获取字符串中字符a[1]
e
[:]获取字符串中的一部分a[1:4]
’ell’
in成员运算符-如果字符串中包含给定的字符串返回 True‘h’ in a
True
not in成员运算符 - 如果字符串中不包含给定的字符返回 True“M” not in a
True

4.2列表

定义列表主要有以下两种方法:

1. 列表生成式

mylist = [x**2 for x in range(1,10)]

#用列表的生成表达式语法创建列表容器
#用这种语法创建列表之后元素已经准备就绪,所以需要耗费较多的内存空间


列表生成器

f = (x ** x for x in range(1,10))
print(f)
for val in f:
print(val)

列表生成器,这里得到的不是一个列表,通过生成器可以获取到数据,它不占用额外的空间存储数据,每次需要数据的时候就通过生成器获取数据,当然这需要额外花费时间。

#斐波拉切数列
def fib(n):

a,b = 0,1
for _ in range(n)
a,b = b,a+b
yield a
#yield表示将函数变成生成器
for val in fib(20):
print(val)

结果如下:

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765


添加和插入对象:

f.append(11)

f.insert(0,2)

mylist = mylist + [20,87]

删除列表中的对象:

del f()

f.index(50,2,5)#查找元素位置,括号是闭区间,如果这里的index值大于len(f),将在列表最后插入对象

f.pop()#找到列表中的值,并将它他列表中删除,默认是最后一个

f.remove()#表示移除一个元素

f.clear()#表示清理所有元素


访问列表:

miylist[0]、mylist()

切片:

[a:b:c]#a代表从多少位开始,b代表从多少位结束,c代表步长


排序:

mylist.sort()
f1 = f[::-1]#对列表反转
f.reverse#反转f,将会改变f

f1 = reversed(f)#不会改变f的反转将会改变mylist列表

mylist1 = mylist.sorted(reserve = True)

#按首字母排序,默认是升序,降序可以通过reverse,新建一个容器来装纳新的数值顺序


4.3元组

Python的元组与列表类似,不同之处在于元组的元素不能修改。

元组使用小括号,列表使用方括号。

元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。

#选出一串数字的最大值和第二大的值
def second_max(x):
(m1,m2) = (x[0],x[1]) if x[0] > x[1] else (x[1],x[0])
for index in range(2,len(x)):
if x[index] > m1:
m2 = m1
m1 = x[index]
elif x[index] > m2:
m2 = x[index]
return m1,m2
#元组

if __name__ == '__main__':
print(second_max([92,32,21,100,22]))


元组与列表最大的区别在于:元组中的对象不能被更改,但我们可以使用del语句来删除整个元组。另外,元组的创建时间比列表要短,

4.4集合

相较于列表和元组是一种无顺序的的容器,形如:set1 = {1,2,4,5,6,2,3}

集合不允许出现相同的值,会自动删除多余的相同值

集合不支持下标运算

set1 = {1,2,4,5,6,2,3}
set1.add(9)
print(set1)
set2 = {2,4,6,7,8}
print(f2)
set3 = set1 & set2求交集
print(set3)
set3 = set1 - set2
print(set3)
set3 = set1 | set2#求并集
print(set3)


运行结果:

{1, 2, 3, 4, 5, 6, 9}
{2, 4, 6, 7, 8}
{2, 4, 6}
{1, 3, 5, 9}
{1, 2, 3, 4, 5, 6, 7, 8, 9}


4.5字典

字典是另一种可变容器模型,且可存储任意类型对象(列表,元组,集合)。

字典的每个键值 key=>value 对用冒号 : 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中 ,格式如下所示:

dic = {key1 : value1, key2 : value2 }


字典有以下特征:

键必须是唯一的,但值则不必。

值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组。

在访问字典中的值时:

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};

print "dict['Name']: ", dict['Name'];
print "dict['Age']: ", dict['Age'];


也可以对字典中的对象进行删除和修改操作:

dict = {'name':'xiangxianzhang','age':22,'class':'Python'}
dict['age'] = 23#将age键的值修改为23
del dict['age']#删除键是age的对象
print(dict)


结果显示:

{'name': 'xiangxianzhang', 'age': 23, 'class': 'Python'}
{'name': 'xiangxianzhang', 'class': 'Python'}


字典值可以没有限制地取任何python对象,既可以是标准的对象,也可以是用户定义的,但键不行。

两个重要的点需要记住:

不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住。

键必须不可变,所以可以用数字,字符串或元组充当,所以不能用列表来充当键。

最后举一个列子:

dictionary = {}
flag = 'a'
pape = 'a'
off = 'a'
while flag == 'a' or
cefc
'c':
flag = input("添加或查找单词 ?(a/c)")
if flag == "a" :                       # 选择添加单词
word = input("输入单词(key):")
defintion = input("输入定义值(value):")
dictionary[str(word)] = str(defintion)  # 添加到字典
print("添加成功!")
pape = input("您是否要查找字典?(a/0)")
if pape == 'a':                        #选择查找字典
print(dictionary)
else :
continue
elif flag == 'c':
check_word = input("要查找的单词:")  # 检索
for key in sorted(dictionary.keys()):            # yes
if str(check_word) == key:
print("该单词存在! " ,key, dictionary[key])
break
else:                                       # no
off = 'b'
print("抱歉,该值不存在!")
else:                               # 停止
print("error type")
break


结果将显示为:

输入单词(key):my_name
输入定义值(value):xiangxianzhang
添加成功!
您是否要查找字典?(a/0)0
添加或查找单词 ?(a/c)c
要查找的单词:my_name
该单词存在!  my_name xiangxianzhang
添加或查找单词 ?(a/c)


5.面向对象

在实际开发应用中,我们不可能把每个代码指令都发给对象来执行,因为那样做非常浪费时间和内存,在以前的软件行业中这都是一个无法避免的问题,直到面向对象这个编程思想的出现。

通常来说面向对象的实际操作流程主要分为三步;

定义一个类,给对象绑定属性。类是对象的蓝图和模板,有了类就可以创建对象,定义类需要做两件事:分析其数据抽象和行为抽象

数据抽象————抽象数据共同的静态特征(找名词)——属性

行为抽象————抽取对象共同的动态特征(找动词)——方法

定义类的关键字——class——类名(每个单词首字母大写)。

class Student(object):
#构造方法 --construtor
#调用该方法的时候,不是直接使用方法的名字而是使用类的名字
def __init__(self, name , age):
#给对象绑定属性,第一步
self.name  =  name
self.age = age
#我们定义一个方法就代表了对象可以接受这个消息
#对象方法的第一个参数同意写成self
#它代表了接收消息的对象
def study(self,course):
print('%s正在学习%s' % (self.name,course))

def watch_av(self):
if self.age >= 18:
print('%s正在观看爱情动作片' % self.name)
else:
print('%s,我们推荐你看喜洋洋' % self.name)
#调用构造方法创建学生对象,第二步
#实际上调用的是构造方法
def main():

stu1 = Student('xxz',22)
stu1.study('python')
#第三步,给对象发消息
#通过给对象发消息,让对象完成某些工作就可以实现某些工作
#解决任何问题都是通过让对象去做事情
stu2 = Student('sjy',15)
stu2.age = 22
stu2.watch_av()

if __name__ == '__main__':
main()


运行结果:

xxz正在学习python
sjy正在观看爱情动作片


#用面向对象的方法来编写一个计时器
import time
class Clock(object):

def __init__(self,hour=0,min=0,sec=0):
self._hour = hour
self._min = min
self._sec = sec

def min(self):
self._sec -= 1
if self._sec == 60:
self._sec = 0
self._min += 1
if self._min == 60:
self._min = 0
self._hour += 1
if self._hour == 24:
self._hour = 0

#下面的方法可以获得对象的字符串表达式
#当我们用print打印对象时会自动调用该方法

def  __str__(self):
return '%02d:%02d:%02d' % (self._hour,self._min,self._sec)
def main():
localtime = time.localtime(time.time())#获取系统时间
clock = Clock(localtime[3],localtime[4],localtime[5])
while True:
print(clock)
sleep(1)
clock.run()
if __name__ == '__main__':
main()


运行结果如下:



我们定义一个类实际上是吧数据和操作数据的函数绑定到一起,形成一个逻辑上的整体,这个整体就叫对象,而且将来任何时候想使用这个对象时直接复用这个类就可以了。

实践出真知,理论知识需要与实际情况相结合,接下来我举几个例子来加深对面向对象这种思想的理解。

6.练习

1.有十步台阶,一个小孩一次最多走三步台阶,问他有多少种走法?

def sum_1_to_100(n):
if n == 1:
return 1
else:
return n + sum_1_to_100(n-1)

def walk(n):
'''

:param n: 走几步台阶
:return: 有多少种走法
'''
if n < 0:
return 0
elif n == 0:
return 1
return walk(n-1) + walk(n-2) +walk(n-3)

if __name__ == '__main__':

print(walk(10))


2.机选双色球,人选注数

from random import randint

def seletcd_ball():
sum_balls = []
red_balls = [x for x in range(1,34)]
for _ in range(6):
seletcd_red_ball = red_balls[randint(0,len(red_balls)-1)]
sum_balls.append(seletcd_red_ball)
red_balls.remove(seletcd_red_ball)
sum_balls.sort()
blue_ball = randint(1,16)
sum_balls.append(blue_ball)
return sum_balls

def foo(balls):
for ball in balls:
print('%02d' % ball,end=' ')
print()

def mains():
n = int(input('下多少注:'))
for _ in range(n):
foo(seletcd_ball())

if __name__ == '__main__':
mains()


3.设计一个显示炸弹倒计时的表

import time
from time import sleep
class  Clock(object):

def __init__(self,hour = 0,min = 0,sec = 0):#类下面的函数上下隔一行
self._hour = hour
self._min = min
self._sec = sec

def run(self):
self._sec -= 1
if self._sec < 0:
self._min -= 1
self._sec = 59
if self._min  < 0:
self._hour -= 1
self._min = 59
if self._hour < 0:
pass

def __str__(self):
return '%02d:%02d:%02d' % (self._hour, self._min, self._sec)

def main():
clock = Clock(0, 1, 1)
while True:
print(clock)
sleep(0.00001)
clock.run()
if  0==clock._hour == clock._min == clock._sec:
print('BOOM SHAKALAKA ')
break
if __name__ == '__main__':
main()


4.在坐标轴上标出两个点,有面向对象的方法求出两点的距离,表达a点移动到b点,表达a点移动多少距离后的点?

from math import sqrt
class Point(object):

def __init__(self,x = 0,y = 0):
self._x = x
self._y = y

def distance(self,x1,y1):
return sqrt(((x1 - self._x)**2 + (y1 - self._y)**2))

def to_second_point(self,x ,y ):
self._x = x
self._y = y

def move_distance(self,dx,dy):
self._x += dx
self._y += dy

def __str__(self):
return '(%s, %s)' % (str(self._x), str(self._y))

def main():
p1 = Point(3,2)
p2 = Point()
print(p1.distance(9,6))
p1.to_second_point(9,6)
print(p1)
p1.move_distance(1,2)
print(p1)

if __name__ == '__main__':
main()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: