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

1. 函数

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

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

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。

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

def f(a,b)

f()
#a和b都是默认值
f(1)
#a0,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(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 1 header 2 header 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)]

#用列表的生成表达式语法创建列表容器
#用这种语法创建列表之后元素已经准备就绪,所以需要耗费较多的内存空间
  1. 列表生成器
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对象,既可以是标准的对象,也可以是用户定义的,但键不行。

两个重要的点需要记住:

  1. 不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住。
  2. 键必须不可变,所以可以用数字,字符串或元组充当,所以不能用列表来充当键。

最后举一个列子:

dictionary = {}
flag = 'a'
pape = 'a'
off = 'a'
while flag == 'a' or '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.面向对象

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

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

    • 数据抽象————抽象数据共同的静态特征(找名词)——属性
    • 行为抽象————抽取对象共同的动态特征(找动词)——方法

定义类的关键字——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()

猜你喜欢

转载自blog.csdn.net/qq_41768400/article/details/79506425