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

Python3学习集合

作者头像
一点儿也不潇洒
发布2018-08-07 10:16:34
1.1K0
发布2018-08-07 10:16:34
举报
文章被收录于专栏:肖洒的博客肖洒的博客

打印

代码语言:javascript
复制
print("hello")
print("这样","可以","连接","起来吗?",",自动识别为空格")
print("试试"+"加好可以连接吗?","事实证明是可以的")
print("100+200 =",100+200)
print(len("abc"))

list的使用

代码语言:javascript
复制
classmates = ["Nicolo","Tom","Jerry"]
print("从开始取:",classmates[0])
print("从末尾取:",classmates[-1])
print("获取list的长度:",len(classmates))
classmates.append('Adam')
print("list中追加元素到末尾:",classmates[-1])
classmates.insert(1, 'Jack')
print("按照索引插值:",classmates[1])
print("要删除list末尾的元素,用pop()方法,删除的东西",classmates.pop())
print("要删除指定位置的元素,用pop(i)方法,其中i是索引位置:", classmates.pop(1))
print("要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:")
classmates[1] = 'Sarah'
print(classmates)

tuple元组

代码语言:javascript
复制
print("tuple一旦初始化就不能修改,比如同样是列出同学的名字")
classmates = ('Michael', 'Bob', 'Tracy')
print(classmates)
# 现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。
# 其他获取元素的方法和list是一样的,你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素。
# 不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。

条件判断

代码语言:javascript
复制
# 输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现:
age = 24
if age > 18:
    print("他的年龄是",age)
    print("他长大了")
else:
    print("他还是个小男孩")

if age >= 18:
    print('adult')
elif age >= 6:
    print('teenager')
else:
    print('kid')

循环

代码语言:javascript
复制
# Python的循环有两种,一种是for...in循环,依次把list或tuple中的每个元素迭代出来
names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print (name)
    # 所以for x in ...循环就是把每个元素代入变量x,然后执行缩进块的语句。

# 计算1-10的整数之和,可以用一个sum变量做累加
sum = 0
for n in [1,2,3,4,5,6,7,8,9,10]:
    sum = sum +n
print(sum)
# 如果要计算1-100的整数之和,从1写到100有点困难,幸好Python提供一个range()函数
# 可以生成一个整数序列,再通过list()函数可以转换为list。
# print(list(range(101)))
sum1 = 0
for n in list(range(101)):
    sum1 = sum1 + n
print(sum1)

定义函数

代码语言:javascript
复制
# 定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:
# 然后,在缩进块中编写函数体,函数的返回值用return语句返回。
# 自定义一个求绝对值的my_abs函数

def my_abs(x):
    if x > 0:
        return x
    else:
        return - x

print(my_abs(0))
print(my_abs(-1))

# 定义空函数
# 占位符作用
def nop():
    pass


# 数据类型检查可以用内置函数isinstance()实现
def my_abs(x):
    if not isinstance(x, (int, float)):
        raise TypeError('bad operand type')
    if x >= 0:
        return x
    else:
        return -x



# 返回多个值
import math

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)
    return nx, ny

函数的参数

代码语言:javascript
复制
# 定义注册函数
def enroll(name,gender,age,city):
    print('name:',name)
    print('gender:',gender)
    print('age:',age)
    print('city:',city)

enroll("Nicolo","male",24,"Xian")

#或定义某几个参数
def enroll2(name,gender,age= 24,city = "Xian"):
    print('name:',name)
    print('gender:',gender)
    print('age:',age)
    print('city:',city)
enroll2("Nicolo","male")

#可变参数
def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum +n
    return sum

#test
print("1-2之和:",calc(1,2))

# Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去
nums = [1,2,3,4,5,6,7,8,9,10]
print("1-10之和:",calc(*nums))
# *nums表示把nums这个list的所有元素作为可变参数传进去。

递归函数

代码语言:javascript
复制
# 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
# 计算阶乘n! = 1 x 2 x 3 x ... x n
def fact(n):
    if n == 1:
        return 1
    return n * fact(n-1)

print(fact(10))
# 使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。

函数作为返回值

代码语言:javascript
复制
# 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
# 通常情况下,求和的函数是这样定义的:

def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax +n
    return ax
print(calc_sum(1,2,3))

# 但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数:
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax +n
        return ax 
    return sum

# 当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:
f = lazy_sum(1, 3, 5, 7, 9)
# 调用函数f时,才真正计算求和的结果:
print(f())

# 在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,
# 当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。


# 闭包

# 注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用

# 小结

# 一个函数可以返回一个计算结果,也可以返回一个函数。

# 返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。

切片

代码语言:javascript
复制

# 1行代码能实现的功能,决不写5行代码。请始终牢记,代码越少,开发效率越高。

#切片
# 取一个list或tuple的部分元素是非常常见的操作
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
# 取前N个元素,也就是索引为0-(N-1)的元素,可以用循环:
print(L[0:3])
print(L[:3])
# L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。

# 从索引1开始,取出2个元素出来:
print(L[1:3])
# 支持倒数切片
print("倒数切片",L[-2:])
print("倒数切片",L[-2:-1])
# 记住倒数第一个元素的索引是-1。

# 其他操作
nums = list(range(100))
print("取前10个:",nums[:10])
print("取后10个:",nums[-10:])
print("取前11-20个数:",nums[11:20])
print("前10个数,每两个取一个:",nums[:10:2])
print("所有数,每5个取一个:",nums[::5])


# tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple
nums2 = (0, 1, 2, 3, 4, 5)[:3]
print(nums2)

# 字符串'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串
str = 'ABCDEFGHIJKMLN'[:4]
print(str)

列表生成器

代码语言:javascript
复制
# 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
# 生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = list(range(1, 11))
print(a)

# 生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?
#方法一
l = []
for x in range(1,11):
    l.append(x*x)
print("方法一",l)

# 方法二
L = [x*x for x in range(1,11)]
print("方法二",L)
# 写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来

# for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
L2 = [x*x for x in range(1,11) if x % 2 ==0]
print("筛选出仅偶数的平方",L2)

# 还可以使用两层循环,可以生成全排列
L3 = [m + n for m in "ABC" for n in "XYZ"]
print("生成全排列",L3)

# 列出当前目录下的所有文件和目录名
# 运用列表生成式,可以写出非常简洁的代码。

import os
L4 = [d for d in os.listdir('.')]
print("列出当前目录下的所有文件和目录名",L4)

# 列表生成式也可以使用两个变量来生成list
d = {'x': 'A', 'y': 'B', 'z': 'C' }
L5 = [k+'='+ v for k,v in d.items()]
print("使用两个变量来生成list",L5)

# 把一个list中所有的字符串变成小写:
L6 = ['Hello', 'World', 'IBM', 'Apple']
L7 = [s.lower() for s in L6]
print("所有的字符串变成小写",L7)

生成器

代码语言:javascript
复制
# 如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
# 这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
# generator保存的是算法

# 第一种方法
# 只要把一个列表生成式的[]改成(),就创建了一个generator
L = [x*x for x in range(1,11)]
print(L)
g = (x*x for x in range(1,11))

# 创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
# 可以通过next()函数获得generator的下一个返回值
print(next(g))
# 这种不断调用next(g)实在是太变态了,正确的方法是使用for循环

for n in g:
    print(n)

# 斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
# 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
# 斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易
def fib(max):
    n,a,b = 0,0,1
    while n<max:
        print(b)
        a,b=b,a+b
        n=n+1
    return 'done'
# fib函数实际上是定义了斐波拉契数列的推算规则
# 要把fib函数变成generator,只需要把print(b)改为yield b就可以了
def fib(max):
    n,a,b = 0,0,1
    while n<max:
        yield b
        a,b=b,a+b
        n=n+1
    return 'done'
    # 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

    # generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
    # 而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

# 举个简单的例子,定义一个generator,依次返回数字1,3,5
def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

# 调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:
# o = odd()
# next(o)

迭代器

代码语言:javascript
复制
# 可以直接作用于for循环的数据类型有以下几种:
# 一类是集合数据类型,如list、tuple、dict、set、str等;
# 一类是generator,包括生成器和带yield的generator function。
# 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
# 可以使用isinstance()判断一个对象是否是Iterable对象

# 而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
# 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
# 可以使用isinstance()判断一个对象是否是Iterator对象:

# 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。
# 在Python中,迭代是通过for ... in来完成的
# Python的for循环抽象程度要高于Java的for循环,因为Python的for循环不仅可以用在list或tuple上,还可以作用在其他可迭代对象上。
# list这种数据类型虽然有下标,但很多其他数据类型是没有下标的,但是,只要是可迭代对象,无论有无下标,都可以迭代,比如dict就可以迭代
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
    print("迭代出key值",key)
    #默认情况下,dict迭代的是key。

# 如果要迭代value,可以用for value in d.values()
for value in d.values():
    print("迭代出value值",value)

# 如果要同时迭代key和value,可以用for k,v in d.items()
for k,v in d.items():
    print("迭代出key和value值",k,v)

map/reduce

代码语言:javascript
复制
# map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
# 比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下
def f(x):
    return x * x
r = map(f,[1,2,3,4,5,6,7,8,9])
print(list(r))
# 结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。

# 一行代码
print(list(map(f,[1,2,3,4,5,6,7,8,9])))

# reduce把一个函数作用在一个序列[x1, x2, x3, ...]上
# 这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
# reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
from functools import reduce
def add(x,y):
    return x + y
print(reduce(add,[1,2,3,4,5,6,7,8,9]))

filter

代码语言:javascript
复制
# filter()函数用于过滤序列
# 和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。


# 在一个list中,删掉偶数,只保留奇数,可以这么写:
def is_odd(n):
    return n % 2 == 1

print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])))

# 把一个序列中的空字符串删掉
def not_empty(s):
    return s and s.strip()
print(list(filter(not_empty,['A','','B','',None,'c','d'])))

sorted

代码语言:javascript
复制
# sorted排序算法
# 排序算法

# 排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。
# 如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。

# Python内置的sorted()函数就可以对list进行排序
# 从小到大
print("一般使用",sorted([112,3,4,54,23,67,85]))

# sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:
print("带参排序",sorted([12,53,-213,-65,2,-52],key = abs))

# 要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True
print("反向排序",sorted([112,3,4,54,23,67,85],reverse=True))

lambda 匿名函数

代码语言:javascript
复制
# 当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。

# 在Python中,对匿名函数提供了有限支持。还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外,还可以直接传入匿名函数:
print(list(map(lambda x: x * x,[1,2,3,4,5,6,7,8,9])))


# 通过对比可以看出,匿名函数lambda x: x * x实际上就是:
# def f(x):
#     return x * x

# 关键字lambda表示匿名函数,冒号前面的x表示函数参数。

# 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
# 用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

f = lambda x: x * x
print("lambda使用",f(5))


# 也可以把匿名函数作为返回值返回
def build(x,y):
    return lambda: x*x + y*y
build(2,3)

# 小结

# Python对匿名函数的支持有限,只有一些简单的情况下可以使用匿名函数。

Decorator装饰器

代码语言:javascript
复制
# 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。
def now():
    print('2017-7-25')
f = now
f()

# 函数对象有一个__name__属性,可以拿到函数的名字:
print(now.__name__)
print(f.__name__)

# # 假设我们要增强now()函数的功能,
# 比如,在函数调用前后自动打印日志,
# 但又不希望修改now()函数的定义,
# 这种在代码运行期间动态增加功能的方式,
# 称之为“装饰器”(Decorator)。
# 本质上,decorator就是一个返回函数的高阶函数。


# 要定义一个能打印日志的decorator,可以定义如下:

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper  

# 观察上面的log,因为它是一个decorator,
# 所以接受一个函数作为参数,并返回一个函数。
# 我们要借助Python的@语法,把decorator置于函数的定义处

@log
def now():
    print('2017-7-25')

# 调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志:

now()

偏函数

代码语言:javascript
复制
# 在介绍函数参数的时候,我们讲到,通过设定参数的默认值,可以降低函数调用的难度。而偏函数也可以做到这一点
# int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换
print("默认十进制",int('123456'))
# 但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:
print("八进制",int('12345',base = 8))

def int2(x, base=2):
    return int(x, base)
print("二进制",int2('1000000'))


# functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2

import functools
int2 = functools.partial(int, base = 2)

# 简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
# 注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:
int2('1000000', base=10)

字典dic和set

代码语言:javascript
复制
# Python内置了字典:dict的支持,dict全称dictionary
# 在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
# 这个通过key计算位置的算法称为哈希算法(Hash)。
# []:list
# ():tuple
# {}: dict

# 学生成绩
score = {"Nicolo":100,"Tom":99,"Jerry":99}
print("打印Nicolo的成绩:",score["Nicolo"])
# 把数据放入dict的方法,除了初始化时指定外,还可以通过key放入
score["Nicolo"] = 101
print("打印Nicolo的成绩:",score["Nicolo"])

# 要避免key不存在的错误,有两种办法,一是通过in判断key是否存在:
print("Nicolo" in score)
# 要删除一个key,用pop(key)方法,对应的value也会从dict中删除:
score.pop("Jerry")
print(score)

# set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。
s  = set([1,2,3])
# 通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果:
s.add(4)
print(s)
# 通过remove(key)方法可以删除元素
s.remove(4)
print("移除后的",s)

模块

代码语言:javascript
复制
# 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里
# 这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式
# 在Python中,一个.py文件就称之为一个模块(Module)

# 使用模块有什么好处?

# 最大的好处是大大提高了代码的可维护性。
# 其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。
# 我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
# 引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。
# 现在,abc.py模块的名字就变成了mycompany.abc,类似的,xyz.py的模块名变成了mycompany.xyz。
# 每一个包目录下面都会有一个__init__.py的文件
# 这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。
# __init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是mycompany。

# 使用模块


# 以内建的sys模块为例,编写一个hello的模块:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

' a test module '
__author__ = 'Nicolo'

import sys

def test():
    args = sys.argv
    if len(args)==1:
        print('Hello, world!')
    elif len(args)==2:
        print('Hello, %s!' % args[1])
    else:
        print('Too many arguments!')

if __name__=='__main__':
    test()

# 第1行和第2行是标准注释,第1行注释可以让这个hello.py文件直接在Unix/Linux/Mac上运行,第2行注释表示.py文件本身使用标准UTF-8编码;

# 第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;

# 第6行使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名;

# 以上就是Python模块的标准文件模板,当然也可以全部删掉不写,但是,按标准办事肯定没错。

# sys模块有一个argv变量,用list存储了命令行的所有参数。argv至少有一个元素,因为第一个参数永远是该.py文件的名称,例如:
# 运行python3 hello.py获得的sys.argv就是['hello.py'];
# 运行python3 hello.py Nicolo获得的sys.argv就是['hello.py', 'Nicolo']。

# 注意到这两行代码:

# if __name__=='__main__':
#     test()

# 在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__
# 而如果在其他地方导入该hello模块时,if判断将失败
# 因此,这种if测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试。


# 安装第三方模块

pip install XXX

面向对象编程

代码语言:javascript
复制
# 如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象
# 然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来。
class Student(object):

    def __init__(self,name,score):
        self.name = name
        self.score = score

    def print_score(self):
        print('%s: %s' % (self.name, self.score))


bart = Student('Bart Simpson', 59)
lisa = Student('Lisa Simpson', 87)
bart.print_score()
lisa.print_score()

类和实例

代码语言:javascript
复制
# ClassANDInstance
# 类和实例
# Python中,定义类是通过class关键字:
class Student1(object):
    pass
# class后面紧接着是类名,即Student,类名通常是大写开头的单词
# 紧接着是(object),表示该类是从哪个类继承下来
# 继承的概念我们后面再讲,通常,如果没有合适的继承类
# 就使用object类,这是所有类最终都会继承的类。

# 定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:
bart1 = Student1()
bart1.name = 'Bart Simpson'

# 由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。
# 通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:
class Student2(object):
    def __init__(self,name,score):
        self.name = name 
        self.score = score

# 注意:特殊方法“init”前后有两个下划线!!!
# 注意到__init__方法的第一个参数永远是self,表示创建的实例本身
# 因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
# 有了__init__方法,在创建实例的时候,就不能传入空的参数了
# 必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:
bart2 = Student2('Bart Simpson', 59)
print("姓名",bart2.name)
print("成绩",bart2.score)

# 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self
# 并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别
# 所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。

# 数据封装

# 面向对象编程的一个重要特点就是数据封装。
# 在上面的Student类中,每个实例就拥有各自的name和score这些数据。
# 我们可以通过函数来访问这些数据,比如打印一个学生的成绩:
# 既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问
# 可以直接在Student类的内部定义访问数据的函数,这样,就把“数据”给封装起来了。
# 这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法:
class Student3(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score

    def print_score(self):
        print('%s: %s' % (self.name, self.score))

# 要定义一个方法,除了第一个参数是self外,其他和普通函数一样。
# 要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:
bart3 = Student3('Nicolo', 99)
bart3.print_score()

private 访问限制

代码语言:javascript
复制
# 果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,
# 在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
# 所以,我们把Student类改一改:

class Student(object):

    def __init__(self, name, score):
        self.__name = name #私有变量
        self.__score = score #私有变量

    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))
# 如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:
class Student(object):
    ...

    #get方法
    def get_name(self):  
        return self.__name

    def get_score(self):
        return self.__score

# 允许外部代码修改score怎么办?可以再给Student类增加set_score方法:

class Student(object):
    ...

    #set方法
    def set_score(self, score):
        self.__score = score

# 在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量
# 特殊变量是可以直接访问的,不是private变量,所以,不能用__name__、__score__这样的变量名。

继承和多态

代码语言:javascript
复制
# 编写了一个名为Animal的class,有一个run()方法可以直接打印:
class Animal(object):
    def run(self):
        print('Animal is running...')
    def eat(self):
        print('Eating meat...')

# 当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:
class Dog(Animal):
    def run(self):
        print('Dog is running...')
    
class Cat(Animal):
    def run(self):
        print('Cat is running...')
# 对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。Cat和Dog类似。
# test
dog = Dog()
dog.run()
dog.eat()

cat = Cat()
cat.run()
# cat.eat()当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。这样,我们就获得了继承的另一个好处:多态。

获取对象信息

代码语言:javascript
复制
# 当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?
# 使用type()

# 首先,我们来判断对象类型,使用type()函数:

# 基本类型都可以用type()判断:
# type(123)

# 使用isinstance()
# 对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

# 使用dir()

# 如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

print(x for x % 7 == 0 in range(101) )

实例属性和类属性

代码语言:javascript
复制
# 由于Python是动态语言,根据类创建的实例可以任意绑定属性。

# 给实例绑定属性的方法是通过实例变量,或者通过self变量:
class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90

# 但是,如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:
class Student(object):
    name = 'Student'

# 在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-08-31,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 打印
  • list的使用
  • tuple元组
  • 条件判断
  • 循环
  • 定义函数
  • 函数的参数
  • 递归函数
  • 函数作为返回值
  • 切片
  • 列表生成器
  • 生成器
  • 迭代器
  • map/reduce
  • filter
  • sorted
  • lambda 匿名函数
  • Decorator装饰器
  • 偏函数
  • 字典dic和set
  • 模块
  • 面向对象编程
  • 类和实例
  • private 访问限制
  • 继承和多态
  • 获取对象信息
  • 实例属性和类属性
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档