python面向对象

类  

下面代码包含,初始化构造函数、类变量、类方法、生成实例、多态性、封装

#!/usr/bin/env python


class Dog(object):
    age = 22  # 类变量, 存在类的内存地址里, 可以被所有实例共享应用

    def __init__(self, name, dog_type, sex):    # self是当前的实例化对象
        self.name = name
        self.dog_type = dog_type
        self.__sex = sex

    def sex(self):
        print('%s sex %s' % (self.name, self.__sex))

    def balk(self):
        print('%s wang.. wang.. wang..' % self.name)

    def eat(self, food):
        print('%s eating %s' % (self.name, food))

d = Dog('dog1', 'yesheng', '')
c = Dog('dog2', 'yesheng', '')
print(d.__sex)  # __对外是访问不到的
d.sex()         # 类中写一个方法可以访问到__sex , 这就是封装
d.balk()
d.eat('sandwish')
d.age = 23  # 修改公共属性,只修改当前实例的
print(d.age)
print(c.age)


def func(obj):  # 一个接口,多种形态 ,obj就是多态性
    obj.balk()

func(d)
func(c)

继承

class Course(object):
    course_name = "Python 自动化"
    period = "7m"
    outline = "sdfsfsdfsfsdf"
    test = 321
    print("in course")

class SchoolMember(object):
    members = 0
    test = 123
    print("in Schoolmember")
    def __init__(self, name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

        SchoolMember.members +=1
        # 每次子类实例化时,执行构造函数里的SchoolMember.members +=1  将members存到类变量里
        # self.members 是 子类实例化调用members后存在新的变量
        print("初始化了一个新学校成员",self.name)

    def tell(self):
        info = '''
        -----info of %s -------
        name: %s
        age : %s
        sex : %s
        '''%(self.name,self.name,self.age,self.sex)
        print(info)

    def __del__(self):#析构方法
        print("%s 被开除了"% self.name)
        SchoolMember.members -=1

class Teacher(SchoolMember):

    def __init__(self,name,age,sex,salary):
        SchoolMember.__init__(self,name,age,sex )
        # super(Teacher,self).__init__(name,age,sex)    #自己找到自己父类
     #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self)
        #self.name = name #t.name =name
        self.salary = salary


    def teaching(self,course):
        print("%s is teaching %s"%(self.name,course))


class Student(SchoolMember,Course):
    def __init__(self,name,age,sex,grade,teacher ):
        SchoolMember.__init__(self,name,age,sex )
        #self.name = name #t.name =name
        self.grade = grade
        self.my_teacher =  teacher



    def pay_tuition(self,amount):
        self.paid_tuition = amount
        print("stduent %s has paid tution amount %s" %(self.name,amount))


t = Teacher("Alex",22,"F",3000)
s = Student("Liuhao",24,"M","pys16", t)
# s2 = Student("YanShuai",46,"F","pys26")
# s4 = Student("NiNing",32,"F","pys26")
print("my teacher",s.my_teacher.name)

s.my_new_teacher = t
print(SchoolMember.members)
print(t.members)
print(SchoolMember.members)
print(s.members)


#del s4
# t.tell()
# s.tell()
# s2.tell()

# t.teaching("python")
# s.pay_tuition(11000)
# print(SchoolMember.members)


# print(s.course_name,s.outline)
# print("test:",s.test)

 抽象类

  抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 

import abc
class AllFile(metaclass=abc.ABCMeta): #抽象类
    def test(self):
        print('testing')
    @abc.abstractmethod
    def read(self):
        pass
    @abc.abstractmethod
    def write(self):
        pass

class Text(AllFile):  #Text继承了AllFile,下面的类方法必须写read、write,如果不写或写错会出现类型错误的异常
    def read(self):
        print('text read')
    def write(self):
        pass

t=Text()
t.test()
# a=AllFile()
# a.test()

类方法

如果我们想通过类来调用方法,而不是通过实例,那应该怎么办呢?

Python 提供了 classmethod 装饰器让我们实现上述功能,看下面的例子:

class A(object):
    bar = 1
    @classmethod
    def class_foo(cls):
        print 'Hello, ', cls
        print cls.bar

>>> A.class_foo()   # 直接通过类来调用方法
Hello,  <class '__main__.A'>
1

在上面,我们使用了 classmethod 装饰方法 class_foo,它就变成了一个类方法,class_foo 的参数是 cls,代表类本身,当我们使用 A.class_foo() 时,cls 就会接收 A 作为参数。另外,被 classmethod 装饰的方法由于持有 cls 参数,因此我们可以在方法里面调用类的属性、方法,比如 cls.bar

静态方法

在类中往往有一些方法跟类有关系,但是又不会改变类和实例状态的方法,这种方法是静态方法,我们使用staticmethod 来装饰,比如下面的例子:

class A(object):
    bar = 1
    @staticmethod
    def static_foo():
        print 'Hello, ', A.bar

>>> a = A()
>>> a.static_foo()
Hello, 1
>>> A.static_foo()
Hello, 1

可以看到,静态方法没有 self 和 cls 参数,可以把它看成是一个普通的函数,我们当然可以把它写到类外面,但这是不推荐的,因为这不利于代码的组织和命名空间的整洁。

强调,注意注意注意:静态方法和类方法虽然是给类准备的,但是如果实例去用,也是可以用的,只不过实例去调用的时候容易让人混淆,不知道你要干啥

特性  

  1 什么是特性property

  property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

import math
class Circle:
    def __init__(self,radius): #圆的半径radius
        self.radius=radius

@property
def area(self):
    return math.pi * self.radius**2 #计算面积

@property
def perimeter(self):
    return 2*math.pi*self.radius #计算周长

c=Circle(10)
print(c.radius)
print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) #同上
'''
输出结果:
10
314.1592653589793
62.83185307179586
'''

注意:此时的特性arear和perimeter不能被赋值

c.area=3 #为特性area赋值
'''
抛出异常:
AttributeError: can't set attribute
'''


  2 为什么要用property

  将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

常用的类特殊成员方法

  __init__ 构造方法,通过类创建对象时,自动触发执行
  __del__ 析构方法,当对象在内存中被释放时,自动触发执行
  __call__ 对象后面加括号,触发执行
  __str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

#!/usr/bin/env python


class MyType(type):
    def __init__(self, *args, **kwargs):  # 第三步
        print("Mytype __init__", *args, **kwargs)

    def __call__(self, *args, **kwargs):
        print("Mytype __call__", *args, **kwargs)
        obj = self.__new__(self)    # 创建实例的内存地址
        print("obj ", obj, *args, **kwargs)
        print(self)
        self.__init__(obj, *args, **kwargs)  # 实例赋值
        return obj  # 把对象返回给实例

    def __new__(cls, *args, **kwargs):  # 第二步
        print("Mytype __new__", *args, **kwargs)
        return type.__new__(cls, *args, **kwargs)   # 调__new__,执行__init__,

print('here...')


class Foo(object, metaclass=MyType):    # 第一步MyType
    def __init__(self, name):
        self.name = name

        print("Foo __init__")

    def __new__(cls, *args, **kwargs):
        print("Foo __new__", cls, *args, **kwargs)
        return object.__new__(cls)

f = Foo("Alex")  # 第四步 ,MyType的__call__方法
print("f", f)
print("fname", f.name)

反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

while True:
    choice = input('[%s]:' % self.username).strip()
    if len(choice) == 0:
        continue
    if choice == 'exit':
        break
    cmd_list = choice.split()
    if hasattr(self, '_%s' % cmd_list[0]):    # 判断输入的命令在类中的方法是否存在
        func = getattr(self, '_%s' % cmd_list[0])    #调用该方法
        func(cmd_list)
    else:
        print('Invalid cmd.')

 

领域模型

  好了,你现在会了面向对象的各种语法了, 那请看下本章最后的作业需求,我相信你可能是蒙蔽的, 很多同学都是学会了面向对象的语法,却依然写不出面向对象的程序,原因是什么呢?原因就是因为你还没掌握一门面向对象设计利器, 你说我读书少别骗我, 什么利器?

  答案就是:领域建模。 从领域模型开始,我们就开始了面向对象的分析和设计过程,可以说,领域模型是完成从需求分析到面向 对象设计的一座桥梁。

  领域模型,顾名思义,就是需求所涉及的领域的一个建模,更通俗的讲法是业务模型。 参考百度百科(http://baike.baidu.cn/view/757895.htm ),领域模型定义如下:

  从这个定义我们可以看出,领域模型有两个主要的作用:

  发掘重要的业务领域概念
  建立业务领域概念之间的关系

  领域建模三字经

  领域模型如此重要,很多同学可能会认为领域建模很复杂,需要很高的技巧。然而事实上领域建模非常简 单,简单得有点难以让人相信,领域建模的方法概括一下就是“找名词”! 许多同学看到这个方法后估计都会笑出来:太假了吧,这么简单,找个初中生都会啊,那我们公司那些分 析师和设计师还有什么用哦?

  分析师和设计师当然有用,后面我们会看到,即使是简单的找名词这样的操作,也涉及到分析和提炼,而 不是简单的摘取出来就可,这种情况下分析师和设计师的经验和技能就能够派上用场了。但领域模型分析 也确实相对简单,即使没有丰富的经验和高超的技巧,至少也能完成一个能用的领域模型。

  虽然我们说“找名词”很简单,但一个关键的问题还没有说明:从哪里找? 如果你还记得领域模型是“需求到面向对象的桥梁”,那么你肯定一下子就能想到:从需求模型中找,具 体来说就是从用例中找。

  归纳一下域建模的方法就是“从用例中找名词”。 当然,找到名词后,为了能够更加符合面向对象的要求和特点,我们还需要对这些名词进一步完善,这就 是接下来的步骤:加属性,连关系!

  最后我们总结出领域建模的三字经方法:找名词、加属性、连关系。   

练习项目:

0:初始化    
		    创建admin用户、密码     
		
1:管理员     
    选项             查看管理员选项     
    创建学校         输入学校名、学校地址,创建成功      
    查看学校         查看所有学校的名称、地址、创建成功       
    创建课程         选择学校,输入程名、课程价格、课程周期,创建成功    
    查看课程 	    查看课程名、价格、周期、校区    
    创建班级         选择课程,输入班级名,创建成功    
    查看班级         查看班级、课程、校区     
    创建老师         选择学校,选择班级,输入老师信息,创建成功     
    查看老师         查看老师、班级、校区
    创建学生         选择学校,选择班级,输入学生信息,创建成功    
    查看学生         查看学生、班级、校区
    退出   	    exit     

2:老师(未实现)    
  选项      查看老师选项
   3:学生 选项 查看学生选项 注册 选择学校,选择班级,输入学生,创建成功 登录 登录学生用户名密码 登录成功 交学费,已交过会提示,没交过进入交款功能 退出 exit

  git:https://github.com/wangyufu/Course_selection

原文地址:https://www.cnblogs.com/wangyufu/p/6566926.html