Python 基础回顾(四)

热身题目
1. 求 n! 也就是 1*2 * 3 * 4.. *n 这个式子的值。
def func(n):
pass

func(3) == 1 * 2 * 3 = 6
func(5) == 6 * 4 * 5 = 120

print func(5) == 120

  1. Alist = [a1,a2… an] 求一个列表中最大的元素
    def maxlist(aslit):
    pass

  2. 统计一段文章中每个词出现的频率 passage = “I have a Dream, do you have one ?

  3. 1* 2 * 3 * 4 =》 f(4) = 4 * f(3) = 4 * (3 * f(2)) = 4 * (3 * (2 * f(1)))
    def f(N):
    if N == 1:
    return 1
    else:
    return N * f(N -1)
    递归
    Pythontutor.com
    import
    sys.getrecursionlimit
    面向对象编程
    Object Oriented Programming,简称OOP,OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。OOP没什么神秘。 OOD是啥?其实是一种程序设计思想。
    面向过程的程序设计把计算机程序视为一系列的命令集合,就是一坨一坨函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
    在Python中,所有数据类型皆为对象,(UNIX里面一切皆是文件?)当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
    假设我们要处理学生的成绩表,为了表示一个学生的成绩,面向过程的程序可以用一个dict表示:
    student1 = { ‘name’: ‘tom’, ‘score’: 85 }
    student2 = { ‘name’: ‘bob’, ‘score’: 81 }
    而处理学生成绩可以通过函数实现,比如打印学生的成绩:
    def print_score(student):
    print ‘%s: %s’ % (student[‘name’], student[‘score’])
    如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是student这种数据类型应该被视为一个对象,这个对象拥有name和score这两个属性(Property)。如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来。

class Student(object):
def init(self, name, score,age = 18):
self.name = name
#self.__name
self.score = score
self.age = age
def get_name(self):
return self.name
def __get_score(self):
return self.score
def print_score(self):
print ‘%s: %s’ % (self.name, self.score)
给对象发消息实际上就是调用对象对应的关联函数,我们称之为对象的方法(Method)。面向对象的程序写出来就像这样:
tom = Student(‘tom’, 99)
type(tom)
type(‘tom’)
lily = Student(‘lily’, 87)
tom.__print_score()
lily.print_score()
print tom.name
tom.name = ‘abc’
print tom.name
print tom.__name
面向对象的设计思想是从现实生活中抽象而来,类(Class)和实例(Instance)的概念是逻辑上一一对应的,类是设计草图,实例是具体实现。Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student。
所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。
面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。

面向对象最重要的概念就是类(Class)和实例(Instance),那如何定义自己想要的类?
在Python中,定义类是通过class关键字:
class Student(object):
pass
class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。
定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

one = Student()
one
<main.Student object at 0x10a67a590>
Student

chengji = 1

一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:
全局变量
局部变量

变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
total = 0; # 这是一个全局变量

定义函数

def sum( arg1, arg2 ):
#返回2个参数的和.”
total = arg1 + arg2; # total在这里是局部变量.
print “函数内是局部变量 : “, total
return total;

sum( 10, 20 );
print “函数外是全局变量 : “, total

继承和多态
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。
比如,我们已经编写了一个名为Animal的class,有一个run()方法可以直接打印:
class Animal(object):
def run(self):
print ‘Animal is running…’
当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:
class Dog(Animal):
pass

class Cat(Animal):
pass
对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。Cat和Dog类似。
继承有什么好处?最大的好处是子类获得了父类的全部功能。由于Animial实现了run()方法,因此,Dog和Cat作为它的子类,什么事也没干,就自动拥有了run()方法:
dog = Dog()
dog.run()

cat = Cat()
cat.run()
运行结果如下:
Animal is running…
Animal is running…
当然,也可以对子类增加一些方法,比如Dog类:
class Dog(Animal):
def run(self):
print ‘Dog is running…’
def eat(self):
print ‘Eating meat…’
继承的第二个好处需要我们对代码做一点改进。你看到了,无论是Dog还是Cat,它们run()的时候,显示的都是Animal is running…,符合逻辑的做法是分别显示Dog is running…和Cat is running…,因此,对Dog和Cat类改进如下:
class Dog(Animal):
def run(self):
print ‘Dog is running…’

class Cat(Animal):
def run(self):
print ‘Cat is running…’
再次运行,结果如下:
Dog is running…
Cat is running…
当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。这样,我们就获得了继承的另一个好处:多态。
练习
F(x) = 1平方+ 2平方。。。 x平方 2种方法 (, 递归)

什么是多态?多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态
要理解什么是多态,我们首先要对数据类型再作一点说明。当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样:
a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型
判断一个变量是否是某个类型可以用isinstance()判断:

isinstance(a, list)
True
isinstance(b, Animal)
True
isinstance(c, Dog)
True
看来a、b、c确实对应着list、Animal、Dog这3种类型。
但是等等,试试:
isinstance(c, Animal)
True
看来c不仅仅是Dog,c还是Animal!
不过仔细想想,这是有道理的,因为Dog是从Animal继承下来的,当我们创建了一个Dog的实例c时,我们认为c的数据类型是Dog没错,但c同时也是Animal也没错,Dog本来就是Animal的一种!
所以,在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行:
b = Animal()
isinstance(b, Dog)
False
Dog可以看成Animal,但Animal不可以看成Dog。
要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个Animal类型的变量:
def run_twice(animal):
animal.run()
animal.run()
当我们传入Animal的实例时,run_twice()就打印出:
A = Animal()
run_twice(A)
Animal is running…
Animal is running…
当我们传入Dog的实例时,run_twice()就打印出:
run_twice(Dog())
Dog is running…
Dog is running…
当我们传入Cat的实例时,run_twice()就打印出:
run_twice(Cat())
Cat is running…
Cat is running…
看上去没啥意思,但是仔细想想,现在,如果我们再定义一个Horse类型,也从Animal派生:
class Horse(Animal):
def run(self):
print ‘Horse is running slowly…’
当我们调用run_twice()时,传入Horse的实例:
run_twice(Horse())
Horse is running slowly…
Horse is running slowly…
你会发现,新增一个Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。
多态的好处就是,当我们需要传入Dog、Cat、Horse……时,我们只需要接收Animal类型就可以了,因为Dog、Cat、Horse……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思:
对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在Animal、Dog、Cat还是Horse对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:
对扩展开放:允许新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。
继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。比如下面的继承树:

Python内置类属性调用实例如下:

!/usr/bin/python

-- coding: UTF-8 --

class Parent: # 定义父类
parentAttr = 100
def init(self):
self.__score = 20
print “调用父类构造函数”
def parentMethod(self):
print ‘调用父类方法’
def setAttr(self, attr):
Parent.parentAttr = attr
Self.__score = attr
def getAttr(self):
print “父类属性 :”, Parent.parentAttr
print “score: ” , self.__score
class Child(Parent): # 定义子类
def init(self):
print “调用子类构造方法”
def childMethod(self):
print ‘调用子类方法 child method’
c = Child() # 实例化子类
c.childMethod() # 调用子类的方法
c.parentMethod() # 调用父类方法
c.setAttr(200) # 再次调用父类的方法
c.getAttr() # 再次调用父类的方法
你可以使用issubclass()或者isinstance()方法来检测。
issubclass() - 布尔函数 判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。

方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法:
class Parent: # 定义父类
def myMethod(self):
print ‘调用父类方法’

class Child(Parent): # 定义子类
def myMethod(self):
print ‘调用子类方法’

c = Child() # 子类实例
c.myMethod() # 子类调用重写方法

小结
继承可以把父类的所有功能都直接拿过来,这样就不必从零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;
有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收;
任何时候,如果没有合适的类可以继承,就继承自object类。
现在回想一下以下几个概念:

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

方法重载:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重载。

实例变量:定义在方法中的变量,只作用于当前实例的类。

继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。

实例化:创建一个类的实例,类的具体对象。

方法:类中定义的函数。

对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

Python内置类属性
dict : 类的属性(包含一个字典,由类的数据属性组成)
doc :类的文档字符串
name: 类名
module: 类定义所在的模块(类的全名是’main.className’,如果类位于一个导入模块mymod中,那么className.module 等于 mymod)
bases : 类的所有父类构成元素(包含了以个由所有父类组成的元组)

class Employee(object):
‘total count’
empCount = 0
def init(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print “Total Employee %d” % Employee.empCount
def displayEmployee(self):
print “Name : “, self.name, “, Salary: “, self.salary

print “Employee.doc:”, Employee.doc
print “Employee.name:”, Employee.name
print “Employee.module:”, Employee.module
print “Employee.bases:”, Employee.bases
print “Employee.dict:”, Employee.dict
执行以上代码输出结果如下:
Employee.doc: 所有员工的基类
Employee.name: Employee
Employee.module: main
Employee.bases: ()
Employee.dict: {‘module‘: ‘main‘, ‘displayCount’: , ‘empCount’: 0, ‘displayEmployee’: , ‘doc‘: ‘\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb’, ‘init‘: }

class chengjidan(object):
def init(self, banjiname):
self.banjiname = banjiname
self.students = []

def add(self, student):
    self.students.append(student)
@classmethod
@property
def max_feng(self, kemu):
    max_f = 0
    for student in self.students:
        chengji = stduent.get_kemu_score(kemu)
        if  chengji > max_f:
            max_f = chengji
    return max_f 



def average_feng(self, kemu):
    pass

def max_zongfeng(self):
    pass

class student(object):
def init(self, name):
self.name = name
self.kemus = {}

def study(self, kemu):
     self.kemus[kemu] = 0

def kaoshi(self, kemu, score):
    self.kemus[kemu]  = score

def get_kemu_score(self, kemu):
    return self.kemus[kemu]

你可能感兴趣的:(Python 基础回顾(四))