精华内容
下载资源
问答
  • 第7.14节 Python类中的实例方法详析一、 实例方法的...定义实例方法与定义函数基本相同,只是Python要求实例方法的第一个形参必须self,也就是实例对象本身,因此实例方法至少应该有一个self参数。关于self的说...

    第7.14节 Python类中的实例方法详析

    一、    实例方法的定义

    在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式:

    1.    类体中定义实例方法

    第一种方式很简单,就是在类体中定义,所有在类中定义的方法默认是实例方法。定义实例方法与定义函数基本相同,只是Python要求实例方法的第一个形参必须为self,也就是实例对象本身,因此实例方法至少应该有一个self参数。关于self的说明,请大家参考老猿前面的章节《》。如下例子:

    class MethodTest():

    def method1(self):print("in method1")

    2.    在类体外将一个函数直接赋值给一个对象实例

    Python 是动态语言,允许为对象动态增加方法,相关步骤如下:

    1)    按照实例方法定义形式在类体外定义一个函数,函数需要将self作为第一个参数;

    2)    使用“实例对象名.方法名=函数”方式在实例中增加方法。

    老猿认为,这种动态定义实例方法,本质上就是动态增加实例变量,只是这个实例变量比较特殊,是个函数类型,对应的赋值也是一个函数。因此上述方法定义的实例方法,与类体中定义的方法还是有差别的,对这种方法Python 不会将实例对象自动绑定到方法的第一个参数,即使将第一个参数命名为 self 也没有用。

    3.    在类体外将一个函数绑定到对象实例

    这种方法与第二种方法本质上是一致的,只是能解决调用时无法自动将实例对象作为第一个实参处理的问题。具体绑定方法如下:

    1)    按照实例方法定义形式在类体外定义一个函数,函数需要将self作为第一个参数;

    2)    使用“实例对象名.方法名 = MethodType(函数, 对象)” 方式在实例中增加方法。

    其中MethodType是从Python的types模块import进来的,通过MethodType可以将函数与实例对象的某个方法进行绑定,调用时就无需再传递实例对象到第一个参数。

    上述第二种和第三种方法都是动态方法,绑定的“实例对象名.方法名”可以是一个已经存在的实例方法,也可以是新定义的一个属性方法,如果是一个已经存在的实例方法,新绑定的函数将替换原实例的方法。

    二、    实例方法的使用

    1.    实例方法可以在类体的实例方法内调用,此时调用方使用“self.方法”方式调用,并在调用传递实参时不需要使用self。请看如下类的定义和调用:

    class MethodTest():

    def method1(self):print("in method1")

    def method2(self):

    print("in method2")

    self.method1()

    上述代码中method2调用了方法method1,使用self方式调用。

    2.    在类体外面调用类体内直接定义的实例方法,直接用“实例名.方法名”方式调用,对于类体内定义的实例方法传实参时无需传递self形参对应的实参,由Python在编译时自动添加实例对象作为第一个实参。请看上面的类定义实例对象后调用method2:

    m1=MethodTest()

    m1.method2()

    上述样例代码执行截图:

    注意:在类外调用实例方法时,无需也不能传递self的实参,由Python解释器自动为其在后面执行时添加。如果定义的方法没有以类方法的方式定义,也没有在方法定义时将self作为第一个形参,编译时并不会报错,但调用该实例方法时会有运行时错误,因为Python会强行绑定实例对象作为第一个参数,因此调用者的实参与定义的形参是一样时,此时会多出一个实参self,导致执行时报参数个数不对的错误。

    3.    在类体外面调用通过函数直接赋值定义的实例方法时,其调用方式与类体内定义的模式不同,要求第一个实参必须是调用的对象本身;

    以上面的类MethodTest为例,如果要增加一个method3的实例方法,其代码如下:

    def dynamicmethond(self):print("in DynamicMethond")

    m1.method3=dynamicmethond

    这样m1这个实例就增加了一个method3方法,调用代码如下:

    m1.method3(m1)  #注意必须在第一个参数将实例自身传递进去

    4.    在类体外面调用通过MethodType绑定的实例方法时,其调用方式与类体内定义的模式相同,第一个形参self对应的实参无需传值,由Python自动添加对应的实例对象;

    以上面的类MethodTest为例,如果要增加一个method4的实例方法进行绑定,其代码如下:

    def dynamicmethond(self):print("in DynamicMethond")

    m1.method4= MethodType(dynamicmethond,m1)

    这样m1这个实例就增加了一个method4方法,且实现了方法与实例的绑定,调用代码如下:

    m1.method4()

    三、    构造方法

    之所以单独介绍构造方法,是因为构造方法是一个特殊的实例方法,具体特殊性包括如下:

    1.    Python的构造方法对所有自定义类名字都固定为__init__,且第一个参数必须为self;

    2.    可以允许开发者没有在类中定义构造方法,此时Python 会自动为该类定义一个只包含一个 self 参数的默认的构造方法;

    3.    构造方法如果有多个形参,除了第一个参数必须是self外,其他参数都是创建实例时在类名后面的括号中给出,也就构造方法的参数就是创建实例时传入的参数,也必须是创建实例时传入;

    4.    构造方法是每个实例定义时自动执行;

    5.    在子类重写构造方法时,必须调用超类(继承的类)的构造方法,否则可能无法正确地初始化对象。

    1)    Python3中所有类都继承于object类,构造函数的重写不用考虑object类的情况,即无需调用object类的构造函数;

    2)    在构造方法中调用父类的构造方法时,可以使用“父类.类名.__init__(self,其他参数)”的方式调用;

    3)    在构造方法中调用父类的构造方法时,可以使用“super().__init__ (参数)”的方式调用,注意此时的参数中不能传递self参数。但这种情况如果存在多个超类时,执行的是第一个超类的构造方法,其实参必须按照第一个超类构造方法的形参来传递,其他超类的构造方法必须通过“父类.类名.__init__(self,其他参数)”的方式调用。

    理解了这几点,结合其他语言的构造方法,就理解了Python的构造方法。

    四、    本节相关代码的完整执行截屏

    本节结合案例详细介绍了实例方法的定义和使用方法,需要注意,动态定义实例方法只影响单个实例自身,对其他实例没有影响。老猿认为动态定义实例方法的使用范围比较有限,如果可能尽量使用类体定义实例方法,仅在特定场景(如动态扩展功能)下使用动态实例方法。

    老猿Python(https://blog.csdn.net/LaoYuanPython)系列文章用于逐步介绍老猿学习Python后总结的学习经验,这些经验有助于没有接触过Python的程序员可以很容易地进入Python的世界。

    欢迎大家批评指正,谢谢大家关注!

    展开全文
  • Python内部函数的self参数

    千次阅读 2019-04-26 10:14:32
    Python中类内部函数的第一参数都是self,这个参数指向调用此函数的类实例。 类内部函数定义时不可以省略self,但是外部函数不需要此函数,理解了self的定义就能理解这一点。 试验中遇到的错误: 在类中的函数...

    Python中类内部函数的第一个参数都是self,这个参数指向调用此函数的类实例。

    类内部函数定义时不可以省略self,但是外部函数不需要此函数,理解了self的定义就能理解这一点。

    试验中遇到的错误:

    在类中的函数定义为:

    def _end_testcase_prompt(testcase,result):

    在类实例中的函数调用为:

    super()._end_testcase_prompt(testcase,diff_result)

    执行时报错:

    ERROR:main:_end_testcase_prompt() takes 2 positional arguments but 3 were given

    这里有两个注意点:

    1.在子类中调用父类的函数,可以用super().+函数名的方式,此时可以省略self

    2.当类实例调用函数时,在执行的时候会默认加上self,比如上面的函数调用在执行时实际执行结果应该是

    父类名称._end_testcase_prompt(子类实例名称,testcase,diff_result)

    此处子类中调用父类函数的四种方式:

    1.直接写类名调用: parent_class.parent_attribute(self)

    2.用 super(type, obj).method(arg)方法调用:super(child_class, child_object).parent_attribute(arg)   【不需要写self】

    3.在类定义中调用本类的父类方法,可以直接 super().parent_method(arg) 

    4.直接用self.parent_method(arg)  【子类在集成父类时,会继承父类的函数】

    展开全文
  • qux被视一个实例方法,因为这是看起来像函数的成员的默认处理(更具体地说,当你看它时,Baz.qux有一个__get__被隐式...方法绑定始终通过绑定到函数的第一参数来工作.如果你聪明的话,你可以亲眼看到这个:class ...

    qux被视为一个实例方法,因为这是看起来像函数的类成员的默认处理(更具体地说,当你看它时,Baz.qux有一个__get__被隐式调用以“绑定”第一个参数到实例通过实例).但是,您没有在开始时提供自我参数.因此,baz被绑定到x lambda参数.

    Python中的“self”这个名字并不神奇;这只是惯例.方法绑定始终通过绑定到函数的第一个参数来工作.

    如果你聪明的话,你可以亲眼看到这个:

    class Baz(object):

    qux = lambda x: x + '_quux'

    def foo(self): return self.qux()

    Baz().foo() # TypeError: unsupported operand type(s) for +: 'Baz' and 'str'

    # because after binding Baz() to 'x', we get Baz() + '_quux'

    一种解决方案是明确地将qux设为静态方法,如Sven Marnach的答案. (你也可以把它变成一个类方法,这是一个特定于Python的概念,它更强大; staticmethod更接近于像Java这样的语言中static static关键字的行为.)注意,就像在Java中一样,你也可以访问static方法foo中的self.qux.这可以通过用staticmethod安装的新机器替换普通的__get__机器来实现.

    另一种解决方案是在lambda参数中提供self参数.如果你实际上不想要“静态”行为(即需要实际对自己做某事),这很有用 – 但它看起来就像你做的那样.为了完整起见,这看起来像:

    qux = lambda self, x: x + '_quux'

    def foo(self):

    return self.qux('foo')

    展开全文
  • 构造函数类中的特殊函数用于描述初始化算法构造函数的作用对象被创建时使用特定的值构造对象,将对象初始化为个特定的初始状态。例如:希望构造个Clock类对象时,将初试时间设0:0:0,就可以通过构造函数来...

    该系列为C++初学者设计

    编写不易,希望获得收藏,关注和转发的支持,谢谢。

    构造函数基本概念

    对类的对象进行初始化,因为这类是新定义的类,所以系统没有相关对象的定义范围,你只能通过自己来定义。

    构造函数

    类中的特殊函数

    用于描述初始化算法

    构造函数的作用

    在对象被创建时使用特定的值构造对象,

    将对象初始化为一个特定的初始状态。

    例如:

    希望在构造一个Clock类对象时,

    将初试时间设为0:0:0,

    就可以通过构造函数来设置。

    构造函数的形式

    函数名与类名相同

    不能定义返回值类型,也不能有return语句

    可以有形式参数,也可以没有形式参数

    可以是内联函数

    可以重载

    可以带默认参数值

    构造函数的调用时机

    在对象创建时被自动调用

    例如

    Clock myclock(0,0,0)

    默认构造函数

    调用时可以不需要实参的构造函数

    ·参数表为空的构造函数

    全部参数都有默认值的构造函数

    下面两个都是默认构造函数

    如在类中同时出现,将产生编译错误

    Clock();

    Clock(int newH=0,int newM=0,int newS=0);

    隐含生成的构造函数

    如果程序中未定义构造函数,编译器将自动生成

    一个默认构造函数

    参数列表为空,不为数据成员设置初始值;

    如果类内定义了成员的初始值,则使用内类定义的初始值;

    如果没有定义类内的初始值,则以默认方式初始化;

    基本类型的数据默认初始化的值是不确定的。

    =default"

    如果程序中已定义构造函数,默认情况下编译器就不再隐含生成

    默认构造函数。如果此时依然希望编译器隐含生成默认构造函数,

    可以使用“=default”

    例:

    class Clock {

    public:

    Clock0 =default;//指示编译器提供默认构造函数

    Clock(int newH, int newM, int newS); //构造函数

    private:

    int hour,minute,second;

    }

    构造函数 ——例题1

    2f2c60a447254a45a124c4b370aad444.png
    10bd42efa78c21eb63d7f25d4abe268e.png

    图2的构造函数定义它的初始化办法是用初始化列表的形式来做的。

    这是一种首选的初始化方法,这样的话就可以简写在函数体中。来进行定义初始化。

    9d0342fc987593b58a9a2b090d2d5d69.png
    c3dca6a064b21b7d67423b7fd7572d6a.png

    一般会多编写一个隐含构造函数,以备在没有参数或者是其他一些情况中使用。

    整体代码

    include

    using namespace std;

    class Clock {//时钟类的定义

    public: //外部接口,公有成员函数

    Clock(int newH, int newM, int newS);//构造函数

    Clock();//默认构造函数

    void setTime(int newH = 0, int newM = 0, int newS = 0);

    void showTime();

    private: //私有数据成员

    int hour, minute, second;

    };

    //时钟类成员函数的具体实现

    Clock::Clock(): hour(0), minute(0), second (0) {}//默认构造函数

    Clock::Clock(int newH, int newM, int news): hour(newH), minute(newM),second(new S)

    void Clock::setTime(int newH, int newM, int newS)

    hour = newH;

    minute = newM;

    second = news;

    inline void Clock::showTime() {

    cout<< hour <

    //主函数

    int main() {

    Clock c(8, 10,0);//自动调用构造函数

    Clock c2; //调用无参数的构造函数

    c. showTime ();

    c2.showTime ();

    return 0;

    委托构造函数

    我们在一个类中重载多个构造函数时发现只有它们的形参表和初始化列表不同外初始化算法相同,函数体都是相同的。为了避免这种重复工作,我们使用到了委托构造函数。

    回顾:

    Clock类的两个构造函数:

    Clock(int newH, int newM, int newS):

    hour(newH), minute(newM), second(newS) //构造函数

    Clock:Clock):hour(0),minute(0),second(0)//默认构造函数

    利用委托构造函数,我们可以将其改进为。

    委托构造函数

    委托构造函数使用类的其他构造函数执行初始化过程

    hour(newH),minute(newM),second(newS){}

    Clock():Clock(0,0,0)() //很明显,在这一步,我们用无参数的构造函数调用了有参数的构造函数,而且这样的好处在于,如果将构造函数进行修改时,可以使其他构造函数协同改变。

    复制构造函数

    本质是用已存在对象去初始化新对象。

    可以用已有对象的引用去做构造函数的参数。

    编译器会在没有定义复制构造函数时定义一个隐含的复制构造函数,会实现两个成员之间对象的一一对应复制。

    复制构造函数定义

    复制构造函数是一种特殊的构造函数,其形参为本类的对象引用.

    作用是用一个已存在的对象去初始化同类型的新对象。

    class 类名(

    类名(形参);//构造函数

    类名(const类名对象名);//复制构造函数

    //...

    类名:类( const 类名&对象名)//复制构造函数的实现

    { 函数体 }

    复制构造函数被调用的三种情况

    定义一个对象时,以本类另一个对象作为初始值,发生复制构造,

    1、如果函数的形参是类的对象,调用函数时,将使用实参对象初始

    化形参对象,发生复制构造;

    2、如果函数的返回值是类的对象,函数执行完成返回主调函数时,

    3、将使用return语句中的对象初始化一个临时无名对象,传递给主

    调函数,此时发生复制构造。

    这种情况也可以通过移动构造避免不必要的复制

    隐含的复制构造函数

    如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成

    一个隐含的复制构造函数。

    这个构造函数执行的功能是:用初始值对象的每个数据成员,初始

    化将要建立的对象的对应数据成员。

    注意,一般来说,默认的复制构造函数在遇见类的成员中有指针情况的时候,隐含的复制构造函数只能达到浅层目标,达不到深层复制的要求。这时就需要自己编写复制构造函数。

    简单的来说,隐含的复制构造函数就是原样照搬。

    而自己定义的复制构造函数则是以自己需求的方式来对对象进行构造。

    “=delete”

    如果不希望对象被复制构造

    C++98做法:将复制构造函数声明为private,并且不提供函数的实现。

    C++11做法:用“=delete”指示编译器不生成默认复制构造函数。

    ·例:

    class Point (//Point 类的定义

    Point(int xx=0, int yy=0)(x=x; y =yy; //构造函数,内联

    Point(const Point& p) =delete; //指示编译器不生成默认复制构造函数

    int x,y; //私有数据

    复制构造函数调用举例

    int getY() const{

    return y;

    private: //私有数据

    int x, y;

    成员函数的实现

    Point::Point(const Point & p){

    X=p.x;

    y = p.y;

    cout << “Calling the coDY constructor" << endl;

    //形参为Point类对象的函数

    void funl(Point n){

    cout <

    //p. setX(1);

    //返回值 为Point类对象的函数。

    fun2(){

    Point a;

    return a;

    //主程序

    int main ()

    Point a; //第一个对象A

    Point b(a); //情况一,用A初始化B。第一次调用拷贝构造函数

    cout << b.getX()<< endl;

    fun1(b) //情况二,对象B作为fun1的实参。第二次调用拷贝构造函数,经调试发现,首先先进入复制构造函数,对形参对象进行初始化,之后再进入fun1函数。

    b = fun2(); //情况三,函数的返回值是类对象,函数返回时,调用复制构造函数。

    cout < b.getX()<< endl;

    讲解:

    之所以复制构造函数在情况三的应,Point a,不调用复制构造函数是因为这是个部分a只是个局部变量,当期和主函数产生联系也就是返回问一个point a这个值,这时才调用复制给我的函数。

    未完待续,谢谢收看 如果喜欢我的系列记得、点赞、收藏、加关注

    展开全文
  • 1)class类包含:类的属性:类中所涉及的变量 类的方法:类中函数2)init函数(方法)1....3.init函数(方法)的第一参数必须是 self(self习惯用法,也可以用别的名字),后续参数则可 以自由指定,和定义函数
  • Python的函数第一类对象(first-class object)。你可以把一个函数复制给变量,或者把函数存储一个结构。可以像参数一样把函数传递进另一个函数,还可以从一个函数中返回另一个函数。知道了这些,有助于理解 ...
  • 关于你的第一个问题,元应该是MyMetaclass(就是这样):In [7]: print(type(MyClass), type(MyDerived))原因是,如果元不是python类型的实例,则通过将这些参数传递给它来调用methaclass name,bases,ns,** kwds(请...
  • 泛型:通俗的讲,比如需要定义一个函数,函数的参数可以接受任意类型。我们不可能一一列举所有的参数类型重载(overload)函数。那么程序引入了个称之泛型的东西,这个类型可以代表任意的数据类型。例如List,...
  • Linux Bash shell 使用函数的一些实例,包括下面的内容:定义函数的格式从函数返回内容使用函数名作为函数指针函数内执行cd命令的影响声明函数内的变量局部变量获取传入函数的所有参数获取传入函数的所有参数在 ...
  • 就是定义在类中的具有特定功能独立段小程序(函数也称之方法) int c=add(3,4); System.out.println("c"+c); public static int add(int a,int b) { returna+b; } /* 修饰符 返回值类型 函数...
  • 1.1 函数的参数分两1.1.1 定义阶段函数内指定的参数称之形式参数,简称形参形参就相当于变量名1.1.2 调用阶段括号内传入的值称之实际参数,简称实参实参就相当于变量值调用函数时会将实参的值绑定给形参,变量...
  • class类中__init__()函数及self参数解析

    千次阅读 2018-03-13 17:14:46
    不能在类的外部被调用或直接访问b.init() ,支持带参数的初始化,例如:def __init__(self,ai_settings,screen):c.init()函数的第一参数必须self(也可是别的名字),后续参数可自由指定3、函数的定义基本形式:...
  • 子父类构造函数的特点:子类的构造函数第一行有一个默认的隐式语句:super(),而super()调用的是父类的空参数的构造函数子类的实例化过程:子类所有的构造函数都会默认访问父类的空参数构造函数什么...
  • Linux Bash shell 使用函数的一些实例,包括下面的内容:定义函数的格式从函数返回内容使用函数名作为函数指针函数内执行cd命令的影响声明函数内的变量局部变量获取传入函数的所有参数获取传入函数的所有参数在 ...
  • 十五讲:派生类构造函数和析构函数  * 理解:派生构造函和析构函数 ...级派生类中定义构造函数一般形式:  派生类构造函数名(总参数表列):基类构造函数名(参数表列)  { 派生类中新增数
  • 概述 实例方法 ... 使用实例调用时,会默认传递实例本身到函数的第一参数,如果函数的参数个数0,则报错; 如果必须这样做,就使用类调用. 普通函数 在类中,尽量不要定义普通函数,会将其当做实例方法使用;
  • 编写函数时,函数中的代码写法和前面学基本一致,只是对代码实现了封装,增加了函数调用、传递参数、返回计算结果等内容。让大家更容易理解,掌握更深刻,我们也要深入内存底层进行分析。绝大多数语言内存...
  • 但是二种和三种就有点不懂了,在类方法的前面加了&,因为QMwidget::animate本身表示函数名,也就是函数的指针,和形参类型相符。但是加&应该是函数指针的地址,但是也能使用,这是什么呢?
  • python函数默认参数为可变对象的理解 1.代码执行的过程,遇到函数...这要从函数的特性说起, Python ,函数是第一类对象(function is the first class object),换而言之,函数也是对象,跟整数、字...
  • 所有Activity中定义一个内部接口,并把要具体执行跳转方法封装这个接口中,并设置参数即可以具体设置显示哪个FragmentViewPager: public interface Fragment2Fragment{ public void gotoFragment...
  • 对于可变参数的函数,C++标准提供了两种方法:1....2. 如果实参类型不同,可以编写可变参数的模板(九章) initializer_list使用方法:他是模板(九章会详细介绍)使用时样例:...
  •     函数定义()出现的参数:形参。形参就是拷贝实参的值,随着函数的调用才产生,随着函数调用结束而销毁。     在函数的外部不能直接使用函数的形参,因为函数调用完毕后,形参被销毁了。 二、实参分类...
  • 第一参数是一个函数,用于表达需要求解非线性方程组,输入如下内容的函数可以运行: <p>``` void WorldFunc1(double* WorldCoord, double* zero, int m, int n, void* ...
  • 1、为什么实例化子的对象的时候会调用先调用父类的构造...答:子类的构造函数中的第一行会隐士的调用 super();子句,即调用了父类的构造函数 如果父类里面没有定义参数为空的构造函数,那么必须子类的构造
  • 1)class包含: ...2.init函数(方法)支持带参数的初始化 ,也可声明该的属性3.init函数(方法)的第一参数必须是 self(self习惯用法,也可以用别的名字),后续参数则可 以自由指定,和定义...
  • 1.class类包含: 类的属性:类中所涉及的变量 类的方法:类中函数 ...init函数(方法)的第一参数必须是 self(self习惯用法,也可以用别的名字),后续参数则可以自由指定,和定义函数没有任何区别。...
  • python类定义的讲解

    2020-12-24 04:43:10
    在类内部方法使用时 self.__private_attrs类方法 在类地内部,使用def关键字可以定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一参数私有类方法 __private_method 两个下划线...
  • 2、注意:在类中的方法【函数的第一参数必须是(self)。这样一来这个参数就是这个类里面的全局变量了,在这个类中的其他函数也就可以使用了,这种做法非常常见。 3、类属性是不通过方法就能获取到,类属性是供...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,006
精华内容 402
关键字:

在类中定义函数的第一参数为