python笔记:类

(※python3)

介绍

python是面向对象程序设计Object-oriented programming(OOP)。

对象指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。

OOP=对象+类+继承+多态+消息。其核心概念就是类和对象。

而python的对象很灵活、概念很广泛。(python自身一个特点)。

面向对象技术:

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

1.定义

类把数据与功能绑定在一起。创建新类就是创建新的对象类型,从而创建该类型的新实例 。

使用class关键字定义类。类的名字一般首字母大写,遵循驼峰命名法。

class Myclass:
    def fun1(self):
        print("my class!")

·类定义内的语句通常都是函数定义,但允许有其他语句。

·类的内部的定义虽然是def,但是称为“方法”。(方法的描述在下面)

·类定义与函数定义 (def 语句) 一样必须被执行才会起作用。 

·进入类定义时,将创建一个新的命名空间,并将其用作局部作用域。

class Classdog:
    def __init__(self, name):
        self.name = name
        self.tricks = []    # 对于传入的每一个self创建一个空列表
    def add_trick(self, trick):
        self.tricks.append(trick)

2.类的成员

主要是数据属性,创建类时变量形式表示的对象属性称为数据成员或成员属性,用函数形式表示的对象行为称为成员方法,成员属性和成员方法统称为类的成员属性包括实例属性和类属性。

·一个对象的特征称为"属性"。一个对象的行为称为"方法"。

·属性在代码层面上来看就是变量,方法实际就是函数,通过调用这些函数来完成某些工作。

·进入类定义时,就会创建一个新的命名空间,并把它用作局部作用域。

 

※一般,实例变量用于每个实例的唯一数据,而类变量用于类的所有实例共享的属性和方法。

※数据属性不需要声明;像局部变量一样,它们将在第一次被赋值时产生。

实例对象

·一般在__init__()中定义,定义和使用必须以self为前缀。

·实例对象所能理解的唯一操作是属性引用。

·外部访问时,作为实例对象,只能通过对象名访问。

类对象

·从结尾处正常离开类定义时,将创建一个类对象。

·类属性属于类对象,可以通过类名或者对象名访问。

·类对象支持两种操作:属性引用和实例化。

class MyClass:
    i = 12345
    #i是一个类属性
    def f(self ,name): # f是一个类对象
            f.name=name # name是一个实例对象     

※python和其他语言不同的是,支持动态的增加成员。

3.类的使用

在调用类中的方法或属性时都必须遵循一定的规则:调用类的属性或方法分类在类中调用、在类外调用。不同地方调用,调用的方式也会有一定的差距。

属性引用

obj.name。使用class_name.attr_name的方式引用类属性(类名.属性名)。

有效的属性名称是类对象被创建时存在于类命名空间中的所有名称。

 类属性可以被赋值,因此可以通过赋值来更改其值。

类的内部调用“自己的”方法时,需要以self为前缀。外部在通过对象名调用方法的时候,不需要传递self。

实例化

实例化对象,并且通过“对象.成员”的方法访问数据成员或成员方法。

格式:实例对象名 = 类名(),实例对象名是新定义的。

class ClassDog:
    weignt=100 # 类属性
    def __init__(self, name):
        self.name = name # 实例属性
        self.tricks = []
    def add_trick(self, trick):
        self.tricks.append(trick)
# 类属性的属性引用
ClassDog.weignt=200 #修改类属性
ClassDog.coolr='blue'#增加新的类属性
# 实例化
dog=ClassDog("John")
dog.add_trick("run")
print(dog.coolr)

·类的实例化使用函数表示法。可以把类对象视为是返回该类的一个新实例的不带参数的函数。

·实例化操作(“调用”类对象)会创建一个空对象。

·许多类喜欢创建带有特定初始状态的自定义实例。 为此类定义可能包含一个名为__init()__的特殊方法。这是一个当创建对象的时候,自动执行的函数。

·像调用函数一样,如果参数传入错误,会引发异常。

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
 
"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

补充1:

也可以使用以下函数的方式来访问属性:

·getattr(obj, name[, default]) : 访问对象的属性。

·hasattr(obj,name) : 检查是否存在一个属性。

·setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。

·delattr(obj, name) : 删除属性。

·isinstance(object,class)可以判断某个方法是否为类的实例。返回值为True||False。

class ClassDog:
    def __init__(self, name):
        self.name = name
        self.tricks = []  
    def add_trick(self, trick):
        self.tricks.append(trick)

d = ClassDog('Fido')
d.add_trick('roll over')
A=1
print(isinstance(d,ClassDog),isinstance(A,ClassDog))

结果:True False。

补充2:

如果同样的属性名称同时出现在实例和类中,则属性查找会优先选择实例。

补充3:内置类属性

  • __dict__ : 类的属性(包含一个字典,由类的数据属性组成)
  • __doc__ :类的文档字符串
  • __name__: 类名
  • __module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
  • __bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

4.私有属性

编程的开闭原则:代码对扩展是开放的,对修改本身是关闭的。

避免直接在对象的外部对变量赋值,python提供了保护机制。(虽然其实并不是严格的访问保护机制。那种仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在。)

·私有成员是为了数据封装和保密而设计的。不能在类地外部被使用或直接访问,在类内部的方法中使用时 self.__private_attrs。

·私有方法就是为了只在类的内部使用。

几种特殊成员:

·__XXX:私有成员。

·_XXX:保护成员,不能用from module import*导入。

·__ XXX__:系统定义的特殊成员。

在IDILE下,输入“class.”会自动显示公有成员,“class._"会显示全部成员。

 5.方法

 粗分为:公有方法;类方法;静态方法;私有方法。

·方法可以通过与普通函数相同的方式引用全局名称。 与方法相关联的全局作用域就是包含其定义的模块。 (类永远不会被作为全局作用域。)

·任何一个作为类属性的函数都为该类的实例定义了一个相应方法。 eg:

# Function defined outside the class
def f1(self, x, y):
    return min(x, x+y)

class C:
    f = f1

    def g(self):
        return 'hello world'
    h = g

类装饰器

·类装饰器类似于函数装饰器的概念,但它应用于类,它们可以用于管理类自身,或者用来拦截实例创建调用以管理实例。

·Python中一切皆对象,函数也可以当做参数传递。装饰器是接收函数作为参数,添加功能后返回一个新函数的函数(类),装饰器既可以通过函数去实现,也可以通过类去实现。

·Python中通过 @ 使用装饰器。

·装饰器模式就是通过实现一个装饰器,在不修改原来函数的情况下就可以增加一些功能。

import time
 
class LogTime:
    def __call__(self, func):
        def _log(*args, **kwargs):
            beg = time.time()
            res = func(*args, **kwargs)
            print('use time: {}'.format(time.time()-beg))
            return res
        return _log
        
@LogTime()     # 一个需要加括号实现一个装饰器的实例
def mysleep():
       time.sleep(1)
    
mysleep()

·当装饰器带有多个参数的时候, 装饰器函数就需要多加一层嵌套。

def decrator(*dargs, **dkargs):
    def wrapper(func):
        def _wrapper(*args, **kargs):
            print ("装饰器参数:", dargs, dkargs)
            print ("函数参数:", args, kargs)
            return func(*args, **kargs)
        return _wrapper
    return wrapper

self参数

在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数。

·类的内部方法类似函数定义,使用参数的方法类似函数使用。

·类的所有实例化方法必须第一个参数是self,(无论是否使用了这个参数)规范。self代表对象本身。

私有方法

以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用他),不能在类地外部调用。

使用@property包装器来包装getter(访问器)和setter(修改器)方法,能够访问和删除到不建议访问|删除的对象。

Python内置的@property装饰器可以把属性变成方法来用,实现的是getter功能。

class Person(object):
    def __init__(self, name, age):
        self._name = name
        self._age = age
 
    # 访问器 getter方法
    @property
    def name(self):
        return self._name
 
    # 访问器 getter方法
    @property
    def age(self):
        return self._age
 
    # 修改器 setter方法
    @age.setter
    def age(self, age):
        self._age = age
 
    def play(self):
        if self._age <= 16:
            print('%s正在画圈圈' % self._name)
        else:
            print('%s正在玩游戏' % self._name)
 
 
def main():
    person = Person('王小王', 12)
    person.play()
    # 修改属性
    person.age = 22
    person.play()
 
    # 如果我们修改name属性
    person.name = '她'  # AttributeError: can't set attribute(不可修改)
 
 
if __name__ == '__main__':
    main()

类方法

是类所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,也可以有别的参数。但是第一个必须是类对象,类似类中的def定义的普通方法第一个参数要是self一样的道理。

静态方法

需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数 。

class People(object):
    country = 'china'
 
    #类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def sum(cls,a,b):
        return a+b        

class Person5:
 
    def __p(self):
        print("这是私有属性") #内部函数也同样可以任意之间互相调用
    def p1(self):
        print("这是p1不是私有方法")
    def p2(self):
        print("这是p2,可以调用p1,也可以调用私有方法__p")
        self.p1()
        self.__p()

class People(object):
    country = 'china'
 
    #类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def sum(cls,a,b):
        return a+b        

class People(object):
    country = 'china'
 
    @staticmethod
    #静态方法,不用定义参数
    def getCountry():
        return People.country
 


特殊方法

 Python类的特殊方法又称为魔术方法,它是以双下划线包裹一个词的形式出现,例如init

·__new__与__init__:__new__是用来构造实例的,而__init__只是用来对返回的实例进行一些属性的初始化。(一般首先都会写一个__init__方法去初始化变量,很少__new__)

·__add__:+

·__sub__:-

·__mul__:*

·__pow__:**

·__str__与__repr__:把类的实例变为字符串。

__str__:用于用户调用,__repr__:用于开发人员调用。

`__setattr__、__getattr__、__getattribute__与__delattr__:见上文。

·__del__()。收回对象的时候由系统自动调用,前提是垃圾回收计数器对该对象的引用必须为0。

6.使用实例

可以参考这一篇:https://blog.csdn.net/zcx1203/article/details/89187495


参考:

《Python程序设计(第三版)》清华大学出版社

https://blog.csdn.net/u013380694/article/details/90019571

·https://blog.csdn.net/qq_37189082/article/details/97302030

·https://blog.csdn.net/weixin_38114487/article/details/103955842

·https://blog.csdn.net/qq_36171645/article/details/89340862

·https://docs.python.org/zh-cn/3/tutorial/classes.html

·https://www.runoob.com/python/python-object.html

·https://blog.csdn.net/qq_39314932/article/details/80716295

·https://zhuanlan.zhihu.com/p/79381718
·https://blog.csdn.net/zcx1203/article/details/89187495


"诚恳,踏实,做好手中热爱的事,相信正义。"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值