Создание классов и объектов

Use __new__ or __init__?

You might have seen very often but the use of is rare. This is because most of the time you don’t need to override it. Generally, is used to initialize a newly created object while is used to control the way an object is created.

We can also use to initialize attributes of an object, but logically it should be inside .

One practical use of , however, could be to restrict the number of objects created from a class.

Suppose we wanted a class for creating instances to represent the four vertices of a square. We can inherit from our previous class (the second example in this article) and use to implement this restriction. Here is an example to restrict a class to have only four instances.

A sample run:

Overview of OOP Terminology

  • Class − A user-defined prototype for an object that defines a set of attributes that characterize any object of the class. The attributes are data members (class variables and instance variables) and methods, accessed via dot notation.

  • Class variable − A variable that is shared by all instances of a class. Class variables are defined within a class but outside any of the class’s methods. Class variables are not used as frequently as instance variables are.

  • Data member − A class variable or instance variable that holds data associated with a class and its objects.

  • Function overloading − The assignment of more than one behavior to a particular function. The operation performed varies by the types of objects or arguments involved.

  • Instance variable − A variable that is defined inside a method and belongs only to the current instance of a class.

  • Inheritance − The transfer of the characteristics of a class to other classes that are derived from it.

  • Instance − An individual object of a certain class. An object obj that belongs to a class Circle, for example, is an instance of the class Circle.

  • Instantiation − The creation of an instance of a class.

  • Method − A special kind of function that is defined in a class definition.

  • Object − A unique instance of a data structure that is defined by its class. An object comprises both data members (class variables and instance variables) and methods.

  • Operator overloading − The assignment of more than one function to a particular operator.

Data Hiding

An object’s attributes may or may not be visible outside the class definition. You need to name attributes with a double underscore prefix, and those attributes then will not be directly visible to outsiders.

Example

#!/usr/bin/python3

class JustCounter:
   __secretCount = 0
  
   def count(self):
      self.__secretCount += 1
      print (self.__secretCount)

counter = JustCounter()
counter.count()
counter.count()
print (counter.__secretCount)

When the above code is executed, it produces the following result −

1
2
Traceback (most recent call last):
   File "test.py", line 12, in <module>
      print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'

Python protects those members by internally changing the name to include the class name. You can access such attributes as object._className__attrName. If you would replace your last line as following, then it works for you −

.........................
print (counter._JustCounter__secretCount)

When the above code is executed, it produces the following result −

1
2
2

Previous Page
Print Page

Next Page  

Constructor

In Python, the constructor method is invoked automatically whenever a new object of a class is instantiated, same as constructors in C# or Java.
The constructor must have a special name and a special parameter called .

Note:

The first parameter of each method in a class must be the self which refers to the calling object.
However, you can give any name to the first parameter, not necessary ‘self’.

The following example defines a constructor.

Example: Constructor
Copy

Now, whenever you create an object of the person class, the constructor method will be called, as shown below.


>>>p1 = person()
Constructor invoked
>>>p2 = person()
Constructor invoked

The constructor in Python is used to define the attributes of an instance and assign values to them.

Why is self explicitly defined everytime?

Even when we understand the use of , it may still seem odd, especially to programmers coming from other languages, that is passed as a parameter explicitly every single time we define a method. As The Zen of Python goes, «Explicit is better than implicit».

So, why do we need to do this? Let’s take a simple example to begin with. We have a class which defines a method to calculate the distance from the origin.

Let us now instantiate this class and find the distance.

In the above example, defines three parameters but we just passed two (6 and 8). Similarly requires one but zero arguments were passed. Why is Python not complaining about this argument number mismatch?

Реализация классификатора

Обучение

Конструктор классификатора будет принимать лишь один аргумент — класс, в котором реализован алгоритм классификации, который мы будем обучать несколько раз:

Так же мы создадим булевое поле, отвечающее за то, является ли модель адаптированной и пустой список для хранения обученных моделей.

Метод, отвечающий за обучение модели, выглядит так:

classes — хранит метки классов

Далее мы перебором по всем меткам обучаем алгоритм. С помощью выбора по маске (true_X = X), мы выбираем «положительные» и «отрицательные» образцы и обучаем новую модель на них. Здесь могут смутить только функции из модуля numpy.

  • np.vstack — просто соединяет массивы вертикально, т. е. просто добавляет строки из второго массива в первый.
  • np.concatenate — объединяет два одномерных массива в один (только здесь, подробнее про эту функцию вы можете почитать здесь).

В конце выставляем булевое поле True и возвращаем сам классификатор для возможности создания цепного интерфейса.

Предсказание классификатора

Здесь всё просто. Мы проходим циклом по всем моделям алгоритма: если она предсказывает 1, то мы возвращаем нужную метку; в противном случае продолжаем.

В конце возвращаем последнюю метку: она вернется, только если все модели «забраковали» текущий образец.

Точность алгоритма

Метод score работает так: он принимает набор образцов и меток к ним, а затем вычисляет соотношение правильно предсказанных меток к их общему кол-ву.

Да-да, метод score также принимает параметр измерения: в процентах или как обычная точность модели (от 0 до 1).

Тестирование классификатора

Мы протестируем наш алгоритм на двух наборах данных: всем известном Iris, а также на наборе Breast Cancer. Схема общая: инициализируем класс, предварительно передав в конструктор модель sklearn, разбиваем набор на обучающие и проверочные выборки и узнаём точность модели.

Iris

Как мы можем заметить, наш алгоритм с логистической регрессией без гиперпараметризации в виде слабого ученика показывает точность 93%. Довольно неплохо, но можно лучше.

Breast Cancer

Здесь мы использовали обычную нейросеть. Наш алгоритм показал точность даже выше, чем сама модель sklearn.

Заключение

Сегодня мы реализовали пошаговый классификатор, используя за основу модели sklearn, и добились неплохих результатов. Однако работа над алгоритмом не закончена, так что подкидываю Вам несколько идей:

  • мы так и не реализовали булевое поле fitted. Подумайте, где бы оно могло пригодиться.
  • нашу модель нельзя сохранить в какой-то файл. Реализуйте метод сохранения классификатора.

Весь код из статьи можно найти здесь.

Overloading Operators

Suppose you have created a Vector class to represent two-dimensional vectors, what happens when you use the plus operator to add them? Most likely Python will yell at you.

You could, however, define the __add__ method in your class to perform vector addition and then the plus operator would behave as per expectation −

Example

#!/usr/bin/python

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2

When the above code is executed, it produces the following result −

Vector(7,8)

Class Inheritance

Instead of starting from a scratch, you can create a class by deriving it from a pre-existing class by listing the parent class in parentheses after the new class name.

The child class inherits the attributes of its parent class, and you can use those attributes as if they were defined in the child class. A child class can also override data members and methods from the parent.

Syntax

Derived classes are declared much like their parent class; however, a list of base classes to inherit from is given after the class name −

class SubClassName (ParentClass1):
   'Optional class documentation string'
   class_suite

Example

#!/usr/bin/python3

class Parent:        # define parent class
   parentAttr = 100
   def __init__(self):
      print ("Calling parent constructor")

   def parentMethod(self):
      print ('Calling parent method')

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print ("Parent attribute :", Parent.parentAttr)

class Child(Parent): # define child class
   def __init__(self):
      print ("Calling child constructor")

   def childMethod(self):
      print ('Calling child method')

c = Child()          # instance of child
c.childMethod()      # child calls its method
c.parentMethod()     # calls parent's method
c.setAttr(200)       # again call parent's method
c.getAttr()          # again call parent's method

When the above code is executed, it produces the following result −

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

In a similar way, you can drive a class from multiple parent classes as follows −

class A:        # define your class A
.....

class B:         # define your calss B
.....

class C(A, B):   # subclass of A and B
.....

You can use issubclass() or isinstance() functions to check a relationships of two classes and instances.

  • The issubclass(sub, sup) boolean function returns True, if the given subclass sub is indeed a subclass of the superclass sup.

  • The isinstance(obj, Class) boolean function returns True, if obj is an instance of class Class or is an instance of a subclass of Class

The __init__() Method

Python has a special method called that you can add to your class. The method is invoked whenever an object is created from the class. Therefore you can make use of the method without having to explictly call it.

Here’s a simple example to demonstrate:

# Create the class
class MyClass:

def __init__(self):
self.a = «Hey»

def b(self):
return «Hello World»

# Create an object from the class
o = MyClass()

# Now we can work with the object
print(o.a)
print(o.b())Result

Hey
Hello World

We can access the variable using (i.e. ). So if we had an object called and another called then we could use and respectively.

Create Multiple Functions

You’d normally put more than one function in a class. You can also pass arguments to the functions as you would any other function.

Here’s an example of a class that groups arithmetic related functions:

# Create the class
class Arithmetic:

def Add(self, x, y):
return x + y

def Subtract(self, x, y):
return x — y

def Multiply(self, x, y):
return x * y

def Divide(self, x, y):
return x / y

# Object 1
a = Arithmetic()
print(a.Add(2, 3))
print(a.Subtract(8, 300))
print(a.Multiply(2, 3))
print(a.Divide(30, 5))

# Object 2
b = Arithmetic()
print(b.Add(22, 33))
print(b.Subtract(88, 3333))
print(b.Multiply(77, 99))
print(b.Divide(555, 444))Result

5
-292
6
6.0
55
-3245
7623
1.25

Accessing Attributes

You access the object’s attributes using the dot operator with object. Class variable would be accessed using class name as follows −

emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

Now, putting all the concepts together −

#!/usr/bin/python

class Employee:
   'Common base class for all employees'
   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

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

When the above code is executed, it produces the following result −

Name :  Zara ,Salary:  2000
Name :  Manni ,Salary:  5000
Total Employee 2

You can add, remove, or modify attributes of classes and objects at any time −

emp1.age = 7  # Add an 'age' attribute.
emp1.age = 8  # Modify 'age' attribute.
del emp1.age  # Delete 'age' attribute.

Instead of using the normal statements to access attributes, you can use the following functions −

  • The getattr(obj, name) − to access the attribute of object.

  • The hasattr(obj,name) − to check if an attribute exists or not.

  • The setattr(obj,name,value) − to set an attribute. If attribute does not exist, then it would be created.

  • The delattr(obj, name) − to delete an attribute.

hasattr(emp1, 'age')    # Returns true if 'age' attribute exists
getattr(emp1, 'age')    # Returns value of 'age' attribute
setattr(emp1, 'age', 8) # Set attribute 'age' at 8
delattr(empl, 'age')    # Delete attribute 'age'
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *