• 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

  • 相关阅读:
    手把手实战:eclipse 搭建 SpringMvc 框架环境
    解决eclipse中Tomcat服务器的server location选项不能修改的问题
    如何解决JSP页面顶端报错 The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
    第二课 --- git的(管理修改和撤销修改、删除文件)
    第二课 ---git时光穿梭(版本回退)
    第一课——git的简介和基本使用
    001——使用composer安装ThinkPHP5
    微信小程序中对于变量的定义
    微信小程序onLaunch修改globalData的值
    7——ThinkPhp中的响应和重定向:
  • 原文地址:https://www.cnblogs.com/wangyufu/p/6566926.html
Copyright © 2020-2023  润新知