PyQt 5 CheckBox State Efficient wAy
I think there is a mistake, this line is defined twice (line 28):

self.check_box2.stateChanged.connect(self.onStateChange)


Therefore the event onStateChange is triggered twice when you check check_box2, which is logical.

I think you did a copy paste and the last should be check_box3. But your naming conventions are not intuitive, give your objects some more meaningful names, otherwise how are you going to tell the difference from your code.

If what you want is mutually exclusive checkboxes the implementation could be more straightforward. Personally I prefer to use radio buttons like in plain HTML because this is more intuitive (it is immediately obvious that only one answer is allowed).

First approach: a generic method that loops on the checkboxes in your form and unchecks all of them except the sender. Then you can simplify code and get rid of if/elif

Second approach: use QT built-in features. You could wrap your checkboxes in a QButtonGroup container.


  A rectangular box before the text label appears when a QCheckBox
  object is added to the parent window. Just as QRadioButton, it is also
  a selectable button. Its common use is in a scenario when the user is
  asked to choose one or more of the available options.
  
  Unlike Radio buttons, check boxes are not mutually exclusive by
  default. In order to restrict the choice to one of the available
  items, the check boxes must be added to QButtonGroup.


and:


  As mentioned earlier, checkBox buttons can be made mutually exclusive
  by adding them in the QButtonGroup object.

self.bg = QButtonGroup()
self.bg.addButton(self.b1,1)
self.bg.addButton(self.b2,2)

  
  QButtonGroup object, provides abstract container for buttons and
  doesn’t have a visual representation. It emits buttonCliked() signal
  and sends Button object’s reference to the slot function btngroup().


Source: PyQt - QCheckBox Widget