对象


# object 为需要继承的父类
class Student(object):
    # 所有类中的方法,第一个参数都是 self,但是实际调用的时候不需要传入
    def __init__(self, name, age):
        # __开头的是私有变量,不允许外部修改
        self.__name = name
        self.age = age

    def setName(self, name):
        self.__name = name

    def show(self):
        print(self.__name)
        print(self.age)


zs = Student('Zhang San', 13)
zs.age = 14
zs.setName('Li si')
zs.show()

获取一个对象的所有属性和方法

print(dir(object))

# 也可以使用help方法获取一些第三方的对象或方法的帮助信息
print(help(object))
print(help(object.method))

对象属性相关方法

class Dog(object):
    def __init__(self, name, age):
        self.__name = name
        self.age = age

    def show(self):
        print(self.__name)


dog = Dog('狗子', 13)

print(hasattr(dog, 'name'))
print(hasattr(dog, 'age'))
print(setattr(dog, '__name', 'fff'))
print(getattr(dog, '__name'))
print(hasattr(Dog, 'show'))

类属性

类属性可以被所有实例使用,如果实例属性和类属性重名,实例属性的优先级更高

class Dog(object):
    name = '狗蛋'


d = Dog()
print(d.name)
print(Dog.name)

动态绑定对象方法

from types import MethodType

class Student(object):
    pass

s = Student()

def setAge(self, age):
    self.age = age

s.setAge = MethodType(setAge, s)
s.setAge(25)  # 动态绑定对象方法,只对当前对象有效
print(s.age)
s1 = Student()
s1.setAge(22)  # 报错

动态绑定类方法

class Student(object):
    pass

s = Student()

def setAge(self, age):
    self.age = age

Student.setAge = setAge

s.setAge(33)
print(s.age)

插槽

__slots__是一个类变量,用于限制类的实例可以拥有的属性。当你定义了一个类时,可以在类的内部声明一个名为__slots__的变量,它是一个包含字符串的元组,每个字符串代表一个允许的属性名称

使用__slots__的主要目的是节省内存。当你创建类的实例时,Python会为每个实例分配一定的内存空间来存储属性

如果你给一个类定义了__slots__,Python就会限制实例只能拥有__slots__中列出的属性,而不是为每个实例动态地分配内存空间。这样可以减少内存的使用,提高性能

from types import MethodType

class Student(object):
    __slots__ = ('name', "age", "setAge")

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)

s = Student('张三', 13)
s.name = '李四'

def setAge(self, age):
    self.age = age

s.setAge = MethodType(setAge, s)
s.setAge(35)
s.show()

s.score = 99  # 不在 __slots__ 范围内的属性或方法不允许动态绑定

property

通过 property 来实现 getter setter


class Student(object):
    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, year):
        self._birth = year

    @property
    def age(self):
        return 2020 - self._birth


s = Student()
s.name = '张三'
s.birth = 1987
s.age = 100        # age是只读的,不可设置
print(s.name, s.birth, s.age)

多重继承

Python 使用 MixIn 设计来实现多重继承,使用起来很简单


# 狗 分别继承了 动物类 和 能跑类
class Dog(Animal,Runable):
    pass

子类调用父类

多重继承下的子类调用父类

这种方式的优点是可以支持多重继承,但是A类会被重复实例化

class A(object):
    def __init__(self):
        print("A init")


class B(A):
    def __init__(self):
        A.__init__(self)
        print("B init")


class C(A):
    def __init__(self):
        A.__init__(self)
        print("C init")


class D(B, C):
    def __init__(self):
        print("D init")
        B.__init__(self)
        C.__init__(self)


d = D()

更建议从设计上避免使用多重继承,然后用super来实现子类调用父类,这样的话基类不会被重复实例化

class A:
    def __init__(self):
        print("A init")

    def test(self):
        print("A test")


class B(A):
    def __init__(self):
        super(B, self).__init__()
        print("B init")
        super(B, self).test()


b = B()

魔术方法

  • __str__ print对象时自定义输出(方法中返回的字符串)
  • __repr__ 交互式解释器自定义输出(方法中返回的字符串),如果__str__没有定义,会调用__repr__
  • __iter__ 使对象可迭代,返回一个迭代对象,如:return iter([1, 2, 2, 3, 4, 5])
  • __next__ 迭代到下一个值
  • __getitem__ 像list那样使用对象, obj()[2],接收一个索引参数
  • __setitem__ obj()[2]=22,接收两个参数:key, value
  • __delitem__ 删除一个元素,del obj()[2],接收一个索引参数
  • __getattr__ 当调用不存在的属性时触发,接收一个参数
  • __dict__ 默认会返回所有属性的键值对字典,对对象进行Json序列化的时候可以使用
  • __call__ 像函数那样直接调用对象时触发object(),跟php的__call不一样(php是调用一个不存在的方法时触发)

更多

枚举类

from enum import Enum, unique

# 枚举类,默认从1开始
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

print(Month.Jan.name)
print(Month.Jan.value)

# 遍历枚举类
for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)

# 自定义枚举类的数值
@unique
class Month2(Enum):
    Jan = 3
    Feb = 4
    Mar = 5
    Apr = 6
    May = 7
    Jun = 8
    Jul = 9
    Aug = 10
    Sep = 11
    Oct = 12
    Nov = 13
    Dec = 14


print(Month2.Jan.name)
print(Month2.Jan.value)

动态创建类

通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class

def fn(self, text):
    print(text)

# 参数1:class的名称
# 参数2:继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法
# 参数3:class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上
Hello = type('Hello', (object,), dict(hello=fn))

h = Hello()
h.hello('ss')

results matching ""

    No results matching ""