暑期学习记录11

python之面向对象

面向对象技术简介

  • 类(Class): 用来描述具有相同的属性方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 实例变量:定义在方法中的变量,只作用于当前实例的类。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
  • 实例化:创建一个类的实例,类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

创建类

使用class语句来创建一个新类,class之后为类的名称并以冒号结尾,如下实例:
class ClassName:
‘类的帮助信息’ #类文档字符串
class_suite #类体

类的帮助信息可以通过ClassName.__doc__查看。
class_suite 由类成员,方法,数据属性组成。
实例

以下是一个简单的Python类实例:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Employee:
   '所有员工的基类'
   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
  • empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。

  • 第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法

  • self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

    类的继承

面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。

需要注意的地方:继承语法 class 派生类名(基类名)://… 基类名写在括号里,基本类是在类定义的时候,在元组之中指明的。

在python中继承中的一些特点:

1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

如果在继承元组中列了一个以上的类,那么它就被称作”多重继承” 。

语法:


#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Parent:        # 定义父类
   parentAttr = 100
   def __init__(self):
      print "调用父类构造函数"

   def parentMethod(self):
      print '调用父类方法'

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print "父类属性 :", Parent.parentAttr

class Child(Parent): # 定义子类
   def __init__(self):
      print "调用子类构造方法"

   def childMethod(self):
      print '调用子类方法 child method'

c = Child()          # 实例化子类
c.childMethod()      # 调用子类的方法
c.parentMethod()     # 调用父类方法
c.setAttr(200)       # 再次调用父类的方法
c.getAttr()          # 再次调用父类的方法

基础重载方法

下表列出了一些通用的功能,你可以在自己的类重写:

序号方法描述 & 简单的调用
1init ( self [,args…] )构造函数简单的调用方法: obj = className(args)
2del( self )析构方法, 删除一个对象简单的调用方法 : del obj
3repr( self )转化为供解释器读取的形式简单的调用方法 : repr(obj)
4str( self )用于将值转化为适于人阅读的形式简单的调用方法 : str(obj)
5cmp ( self, x )对象比较简单的调用方法 : cmp(obj, x)

运算符重载

Python同样支持运算符重载,实例如下:


#!/usr/bin/python

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)

   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2

以上代码执行结果如下所示:

Vector(7,8)

类属性与方法
类的私有属性

__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法

在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 self.__private_methods

ython不允许实例化的类访问私有数据,但你可以使用 object._className__attrName 访问属性(伪私有)


#!/usr/bin/python
# -*- coding: UTF-8 -*-

class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0    # 公开变量

    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print self.__secretCount

counter = JustCounter()
counter.count()
counter.count()
print counter.publicCount
print counter.__secretCount  # 报错,实例不能访问私有变量
#替换最后一行:.........................
print counter._JustCounter__secretCount

Python super() 函数
描述
super() 函数用于调用下一个父类(超类)并返回该父类实例的方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
语法
以下是 super() 方法的语法:

super(type[, object-or-type])
参数

type -- 类。
object-or-type -- 类,一般是 self

返回值
无。

实例


#!/usr/bin/python
# -*- coding: UTF-8 -*-

class FooParent(object):
    def __init__(self):
        self.parent = 'I\'m the parent.'
        print 'Parent'

    def bar(self,message):
        print message,'from Parent'

class FooChild(FooParent):
    def __init__(self):
        # super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类B的对象 FooChild 转换为类 FooParent 的对象
        super(FooChild,self).__init__()    
        print 'Child'

    def bar(self,message):
        super(FooChild, self).bar(message)
        print 'Child bar fuction'
        print self.parent

if __name__ == '__main__':
    fooChild = FooChild()
    fooChild.bar('HelloWorld')

执行结果:

Parent
Child
HelloWorld from Parent
Child bar fuction
I'm the parent.

python练习实例1:
题目:有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少?
程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列

①使用列表:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 原答案没有指出三位数的数量,添加无重复三位数的数量
d=[]
for a in range(1,5):
    for b in range(1,5):
        for c in range(1,5):
            if (a!=b) and (a!=c) and (c!=b):
                d.append([a,b,c])
print "总数量:", len(d)
print d

②使用自带函数
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from itertools import permutations
for i in permutations([1, 2, 3, 4], 3):#i返回的是长度为3的不重复数字的集合
    k = ''
    for j in range(0, len(i)):
        k = k + str(i[j])#将元素转化成字符然后连接起来
    print (int(k))#可不转换类型

结果:
123
124
132
134
142
143
213
214
231
234
241
243
312
314
321
324
341
342
412
413
421
423
431
432


Python 练习实例2

题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数?

程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。

①利用列表索引一一对应,比if-elif-else简洁
#!/usr/bin/python
# -*- coding: UTF-8 -*-

i = int(raw_input('净利润:'))
arr = [1000000,600000,400000,200000,100000,0]
rat = [0.01,0.015,0.03,0.05,0.075,0.1]
r = 0
for idx in range(0,6):
    if i>arr[idx]:
        r+=(i-arr[idx])*rat[idx]
        print (i-arr[idx])*rat[idx]
        i=arr[idx]
print r

Python 练习实例3

题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
程序分析:
假设该数为 x。
1、则:x + 100 = n2, x + 100 + 168 = m2
2、计算等式:m2 - n2 = (m + n)(m - n) = 168
3、设置: m + n = i,m - n = j,i * j =168,i 和 j 至少一个是偶数
4、可得: m = (i + j) / 2, n = (i - j) / 2,i 和 j 要么都是偶数,要么都是奇数。
5、从 3 和 4 推导可知道,i 与 j 均是大于等于 2 的偶数。
6、由于 i * j = 168, j>=2,则 1 < i < 168 / 2 + 1。
7、接下来将 i 的所有数字循环计算即可。

①按照程序分析:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

for i in range(1,85):
    if 168 % i == 0:
        j = 168 / i;
        if  i > j and (i + j) % 2 == 0 and (i - j) % 2 == 0 :
            m = (i + j) / 2
            n = (i - j) / 2
            x = n * n - 100
            print(x)

②直接从题目信息中用遍历查找:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
for m in range(168):
    for n in range(m):
        if (m+n)*(m-n)==168:
            x=n**2-100
            print "符合条件的整数有:",x
③利用集合方法:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#X1=N*2-100的合集
x1 = map(lambda i:i**2-100,range(1,100))
#X2=M*2-100-168的合集
x2 = map(lambda i:i**2-100-168,range(1,100))
#两个合集求并集结果
print set(list(x1)) & set(list(x2))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值